home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / comm / term / term34Source.lha / termGadTools.c < prev    next >
C/C++ Source or Header  |  1993-07-16  |  78KB  |  3,731 lines

  1. /*
  2. **    termGadTools.c
  3. **
  4. **    GadTools object management support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifdef DEBUG
  11. #include "termDebug.h"
  12. #endif    /* DEBUG */
  13.  
  14.     /* Some includes for starters. */
  15.  
  16. #include <intuition/intuition.h>
  17. #include <intuition/gadgetclass.h>
  18. #include <libraries/gadtools.h>
  19. #include <intuition/sghooks.h>
  20. #include <utility/tagitem.h>
  21. #include <exec/libraries.h>
  22. #include <exec/memory.h>
  23.  
  24. #include <clib/intuition_protos.h>
  25. /*#include <clib/gadtools_protos.h>*/
  26. #include <clib/diskfont_protos.h>
  27. #include <clib/graphics_protos.h>
  28. #include <clib/utility_protos.h>
  29. #include <clib/exec_protos.h>
  30.  
  31. #include <string.h>
  32. #include <stdarg.h>
  33.  
  34.     /* Some useful minterms. */
  35.  
  36. #define MINTERM_COPY        ABC | ABNC | NABC | NABNC
  37. #define MINTERM_NOT_C        ABNC | ANBNC | NABNC | NANBNC
  38. #define MINTERM_NOT_B_AND_C    ANBC | NANBC
  39. #define MINTERM_B_OR_C        ABC | ABNC | NABC | NABNC | ANBC | NANBC
  40.  
  41.     /* User interface definitions. */
  42.  
  43. #define SZLV_Display    1        /* Listview includes display */
  44. #define SZLV_String    2        /* Listview includes string */
  45.  
  46. #define FOLDER_KIND    42        /* Folder selection button. */
  47. #define FILE_KIND    43        /* File selection button. */
  48. #define PASSWORD_KIND    44        /* Password entry string gadget. */
  49. #define SCREEN_KIND    45        /* Screen selection button. */
  50.  
  51. #define SZ_Adjust    TAG_USER+1    /* Adjust object */
  52. #define SZ_AutoWidth    TAG_USER+2    /* Use default width? */
  53. #define SZ_AlignExtra    TAG_USER+3    /* Add extra space to top edge */
  54. #define SZ_NewColumn    TAG_USER+4    /* Start new column */
  55. #define SZ_Lines    TAG_USER+5    /* Number of lines in object */
  56. #define SZ_Chars    TAG_USER+6    /* Number of chars (width) in object */
  57. #define SZ_AlignLeft    TAG_USER+7    /* Align to left border */
  58. #define SZ_AlignRight    TAG_USER+8    /* Align to right border */
  59. #define SZ_AlignCentre    TAG_USER+9    /* Centre it */
  60. #define SZ_AlignBottom    TAG_USER+10    /* Align to window bottom */
  61. #define SZ_GroupCount    TAG_USER+11    /* Create a group with N objects */
  62. #define SZ_GroupNext    TAG_USER+12    /* Skip to next position */
  63. #define SZ_SaveX    TAG_USER+13    /* Place left to current object, don't touch the left edge position, though. */
  64. #define SZ_SaveY    TAG_USER+14    /* Place below current object, don't touch the top edge position, though. */
  65. #define SZ_UseLeft    TAG_USER+15    /* Use this coordinate as left edge. */
  66. #define SZ_UseTop    TAG_USER+16    /* Use this coordinate as top edge. */
  67. #define SZ_UseWidth    TAG_USER+17    /* Use this gadget width. */
  68. #define SZ_UseHeight    TAG_USER+18    /* Use this gadget height. */
  69. #define SZ_FullWidth    TAG_USER+19    /* Use full window width for gadget. */
  70. #define SZ_FullHeight    TAG_USER+20    /* Use full window height for gadget. */
  71. #define SZ_SmallSpace    TAG_USER+21    /* Provide small alignment space. */
  72. #define SZ_LeaveFolder    TAG_USER+22    /* Leave space for folder icon. */
  73. #define SZ_PlaceLeft    TAG_USER+23    /* Place left to current object, don't modify next object position. */
  74. #define SZ_PlaceBelow    TAG_USER+24    /* Place below current object, don't modify next object position. */
  75. #define SZ_InterHeight    TAG_USER+25    /* Use this inter-object space. */
  76.  
  77.     /* Box information types. */
  78.  
  79. enum    {    BOX_LEFT,BOX_TOP,BOX_WIDTH,BOX_HEIGHT };
  80.  
  81.     /* Use these macros if the corresponding functions are not available. */
  82.  
  83. extern ULONG            (* __regargs ReadAPen)(struct RastPort *RPort);
  84. extern ULONG            (* __regargs ReadBPen)(struct RastPort *RPort);
  85. extern ULONG            (* __regargs ReadDrMd)(struct RastPort *RPort);
  86.  
  87.     /* Image types */
  88.  
  89. enum    {    BUTTONIMAGE_FOLDER, BUTTONIMAGE_FILE, BUTTONIMAGE_SCREEN };
  90.  
  91.     /* External data. */
  92.  
  93. extern struct Library        *GadToolsBase,
  94.                 *DiskfontBase;
  95. extern struct Gadget        *ActiveGadget;
  96. extern UBYTE             SharedBuffer[];
  97. extern struct TextAttr         UserFont;
  98. extern APTR             VisualInfo;
  99. extern LONG             InterWidth,
  100.                  InterHeight;
  101. extern struct Hook         CommandHook,
  102.                  PasswordHook;
  103. extern struct TextFont        *UserTextFont;
  104.  
  105.     /* This structure will help us to remember the current state of
  106.      * a GadTools object.
  107.      */
  108.  
  109. struct GadgetSupportInfo
  110. {
  111.     STRPTR                 Original,    /* Password string entry, original contents (for undo). */
  112.                      Buffer;    /* Password string entry, current contents. */
  113.  
  114.     struct GadgetSupportInfo    *PointBack;    /* Points back to itself. */
  115.     struct Gadget            *Gadget;    /* Points back to the host. */
  116.  
  117.     struct Image            *Image;        /* Folder images. */
  118.  
  119.     STRPTR                 Title;        /* New gadget title. */
  120.  
  121.     WORD                 Kind;        /* Item type (BUTTON_KIND, STRING_KIND, etc.) */
  122.     UBYTE                 Key;        /* The key to press. */
  123.     BYTE                 ReadOnly;    /* LISTVIEW_KIND only: is this a read-only object? */
  124.     LONG                 Current,    /* Current state or counter. */
  125.                      Min,        /* Minimum value for `Current'. */
  126.                      Max;        /* Maximum value for `Current'. */
  127.     UWORD                 Flags;        /* Miscellaneous flag values. */
  128. };
  129.  
  130.     /* A text box for several lines of text. */
  131.  
  132. struct TextBox
  133. {
  134.     struct TextBox    *NextBox;        /* Next box in chain. */
  135.  
  136.     LONG         Left,Top,        /* Position and size. */
  137.              Width,Height;
  138.  
  139.     LONG         LineWidth,        /* Line width in pixels. */
  140.              LineHeight;        /* Line height in pixels. */
  141.  
  142.     LONG         NumChars,        /* Number of chars per line. */
  143.              NumLines;        /* Number of lines. */
  144.  
  145.     STRPTR        *Title,            /* Line titles. */
  146.             *Text;            /* Line texts. */
  147.  
  148.     LONG         TitleFgPen,
  149.              TitleBgPen,
  150.              TextPen;
  151. };
  152.  
  153.     /* Our home-made tag items. */
  154.  
  155. STATIC Tag PrivateTags[] =
  156. {
  157.     SZ_Adjust,
  158.     SZ_AutoWidth,
  159.     SZ_AlignExtra,
  160.     SZ_NewColumn,
  161.     SZ_Lines,
  162.     SZ_Chars,
  163.     SZ_AlignLeft,
  164.     SZ_AlignRight,
  165.     SZ_AlignCentre,
  166.     SZ_AlignBottom,
  167.     SZ_GroupCount,
  168.     SZ_GroupNext,
  169.     SZ_SaveX,
  170.     SZ_SaveY,
  171.     SZ_UseLeft,
  172.     SZ_UseTop,
  173.     SZ_UseWidth,
  174.     SZ_UseHeight,
  175.     SZ_FullWidth,
  176.     SZ_FullHeight,
  177.     SZ_SmallSpace,
  178.     SZ_LeaveFolder,
  179.     SZ_PlaceLeft,
  180.     SZ_PlaceBelow,
  181.     SZ_InterHeight,
  182.  
  183.     TAG_DONE
  184. };
  185.  
  186.     /* Sizing data. */
  187.  
  188. STATIC struct RastPort    *SZ_RPort;
  189. STATIC struct TextFont    *SZ_TextFont;
  190. STATIC struct Screen    *SZ_Screen;
  191.  
  192. STATIC LONG         SZ_Left,
  193.              SZ_Top,
  194.              SZ_WindowWidth,
  195.              SZ_WindowHeight;
  196.              SZ_CurrentLeft,
  197.              SZ_CurrentTop,
  198.              SZ_CurrentWidth,
  199.              SZ_MaxWidth,
  200.              SZ_GroupDelta,
  201.              SZ_GroupX,
  202.              SZ_WidthMax,
  203.              SZ_TextPen,
  204.  
  205.              SZ_LastLeft,
  206.              SZ_LastTop,
  207.              SZ_LastWidth,
  208.              SZ_LastHeight;
  209.  
  210.     /* Dimensions of the font glyphs. */
  211.  
  212. STATIC ULONG         SZ_AverageGlyphWidth,    /* Average width. */
  213.              SZ_MaxGlyphWidth,    /* Maximum width. */
  214.              SZ_MaxNumericWidth;    /* Maximum numeral width. */
  215.  
  216.     /* AmigaGuide help. */
  217.  
  218. extern VOID            GuideSetup(VOID);
  219.  
  220.     /* Local routines. */
  221.  
  222. struct Gadget *            CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...);
  223. VOID                FreeGadgets(struct Gadget *GadgetList);
  224. VOID                GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...);
  225. VOID                GT_ReplyIMsg(struct IntuiMessage *Message);
  226.  
  227. VOID                KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code);
  228.  
  229.     /* Sizing routines. */
  230.  
  231. LONG                SZ_GetWindowWidth(VOID);
  232. LONG                SZ_GetWindowHeight(VOID);
  233. LONG                SZ_GetLeftEdge(VOID);
  234. LONG                SZ_GetTopEdge(VOID);
  235. VOID __regargs            SZ_SetTopEdge(LONG Top);
  236. VOID __regargs            SZ_SetLeftEdge(LONG Left);
  237. VOID __regargs            SZ_SetAbsoluteTop(LONG Top);
  238. VOID __regargs            SZ_SetAbsoluteLeft(LONG Left);
  239. VOID __regargs            SZ_SetWidth(LONG Width);
  240. VOID                SZ_InitWidth(VOID);
  241. LONG                SZ_ResetMaxWidth(VOID);
  242. VOID __regargs            SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  243.  
  244. VOID __regargs            SZ_GetDimension(LONG *Width,LONG *Height);
  245. LONG __regargs            SZ_TextWidth(STRPTR String);
  246. VOID __regargs            SZ_AddLeftOffset(LONG Offset);
  247. LONG __stdargs            SZ_LeftOffsetN(LONG DataArray,...);
  248. LONG __regargs            SZ_LeftOffsetDelta(LONG From,LONG To);
  249. VOID                SZ_SizeCleanup(VOID);
  250. BYTE __regargs            SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title);
  251. ULONG __regargs            SZ_GetNumericLen(STRPTR String);
  252. ULONG __regargs            SZ_GetGlyphLen(STRPTR String);
  253. ULONG __regargs            SZ_GetLen(STRPTR String);
  254. LONG __regargs            SZ_Height(UBYTE Type,LONG Lines,BYTE Display);
  255. LONG __regargs            SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  256.  
  257.     /* Text box routines. */
  258.  
  259. VOID __regargs            SZ_FreeBox(struct TextBox *Box);
  260. VOID __regargs            SZ_FreeBoxes(struct TextBox *FirstBox);
  261. LONG __regargs            SZ_BoxWidth(LONG Chars);
  262. LONG __regargs            SZ_BoxHeight(LONG Lines);
  263. VOID __regargs            SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen);
  264. struct TextBox * __stdargs    SZ_CreateTextBox(struct TextBox **FirstBox,...);
  265. VOID __stdargs            SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...);
  266. VOID __regargs            SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String);
  267. VOID __stdargs            SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...);
  268. VOID __regargs            SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box);
  269. VOID __regargs            SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox);
  270. VOID __regargs            SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top);
  271. VOID __regargs            SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
  272. VOID __regargs            SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top);
  273. VOID __regargs            SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
  274. LONG __regargs            SZ_GetBoxInfo(struct TextBox *Box,LONG Type);
  275.  
  276.     /* The original gadtools.library routines. */
  277.  
  278. struct Gadget *            OldCreateGadgetA(ULONG,struct Gadget *,struct NewGadget *,struct TagItem *);
  279. VOID                OldFreeGadgets(struct Gadget *);
  280. VOID                OldGT_SetGadgetAttrsA(struct Gadget *,struct Window *,struct Requester *,struct TagItem *);
  281. VOID                OldGT_ReplyIMsg(struct IntuiMessage *);
  282. VOID                DrawBevelBox(struct RastPort *,LONG,LONG,LONG,LONG,...);
  283.  
  284.     /* Pragma calls: the easy way. */
  285.  
  286. #pragma libcall GadToolsBase OldCreateGadgetA 1E A98004
  287. #pragma libcall GadToolsBase OldFreeGadgets 24 801
  288. #pragma libcall GadToolsBase OldGT_SetGadgetAttrsA 2A BA9804
  289. #pragma libcall GadToolsBase OldGT_ReplyIMsg 4E 901
  290.  
  291.     /* CreateButtonImages():
  292.      *
  293.      *    Create images for the folder and file buttons.
  294.      */
  295.  
  296. STATIC struct Image *
  297. CreateButtonImages(BYTE Type,UWORD Width,UWORD Height,struct Screen *Screen,APTR VisualInfo)
  298. {
  299.     struct Image *Image = NULL;
  300.  
  301.         /* Minimum size required. */
  302.  
  303.     if(Width >= 16 && Height >= 12)
  304.     {
  305.         struct RastPort    *RPort;
  306.  
  307.             /* Allocate local dummy rastport. */
  308.  
  309.         if(RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
  310.         {
  311.             struct BitMap    *BitMap[2] = { NULL, NULL };
  312.             BYTE         Success;
  313.             WORD         Depth,
  314.                      i,j;
  315.  
  316.                 /* Determine screen depth. */
  317.  
  318.             Depth = Screen -> RastPort . BitMap -> Depth;
  319.  
  320.                 /* Set up rastport. */
  321.  
  322.             InitRastPort(RPort);
  323.  
  324.                 /* Allocate bitmaps and bitplane data. */
  325.  
  326.             Success = TRUE;
  327.  
  328.             for(i = 0 ; Success && i < 2 ; i++)
  329.             {
  330.                 if(BitMap[i] = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
  331.                 {
  332.                     InitBitMap(BitMap[i],Depth,Width,Height);
  333.  
  334.                     if(BitMap[i] -> Planes[0] = (PLANEPTR)AllocVec(BitMap[i] -> BytesPerRow * BitMap[i] -> Rows * BitMap[i] -> Depth,MEMF_CHIP | MEMF_CLEAR))
  335.                     {
  336.                         for(j = 1 ; j < Depth ; j++)
  337.                             BitMap[i] -> Planes[j] = BitMap[i] -> Planes[j - 1] + BitMap[i] -> BytesPerRow * BitMap[i] -> Rows;
  338.                     }
  339.                     else
  340.                         Success = FALSE;
  341.                 }
  342.                 else
  343.                     Success = FALSE;
  344.             }
  345.  
  346.                 /* Did we get what we wanted? */
  347.  
  348.             if(Success)
  349.             {
  350.                 struct DrawInfo *DrawInfo;
  351.  
  352.                     /* Get drawing pen information. */
  353.  
  354.                 if(DrawInfo = GetScreenDrawInfo(Screen))
  355.                 {
  356.                         /* Run-dump of the folder image. */
  357.  
  358.                     STATIC UWORD __chip FolderData[10] =
  359.                     {
  360.                         0x03C0,
  361.                         0x0420,
  362.                         0xF810,
  363.                         0xFC10,
  364.                         0xC3F0,
  365.                         0xC010,
  366.                         0xC010,
  367.                         0xC010,
  368.                         0xC010,
  369.                         0xFFF0
  370.                     };
  371.  
  372.                         /* Run-dump of the file image. */
  373.  
  374.                     STATIC UWORD __chip FileData[10] =
  375.                     {
  376.                         0xFF00,
  377.                         0x8180,
  378.                         0x8140,
  379.                         0x8120,
  380.                         0x81F0,
  381.                         0x8010,
  382.                         0x8010,
  383.                         0x8010,
  384.                         0x8010,
  385.                         0xFFF0
  386.                     };
  387.  
  388.                         /* Run-dump of the screen image. */
  389.  
  390.                     STATIC UWORD __chip ScreenData[10] =
  391.                     {
  392.                         0xFFF0,
  393.                         0x8050,
  394.                         0xFFF0,
  395.                         0x8010,
  396.                         0x8010,
  397.                         0x8010,
  398.                         0x8010,
  399.                         0x8010,
  400.                         0x8010,
  401.                         0xFFF0
  402.                     };
  403.  
  404.                     struct BitMap __aligned    FolderBitMap;
  405.                     WORD            Left,
  406.                                 Top;
  407.  
  408.                         /* Determine image offsets. */
  409.  
  410.                     Left    = (Width - 12) / 2;
  411.                     Top    = (Height - 10) / 2;
  412.  
  413.                         /* Set up the folder bitmap. */
  414.  
  415.                     InitBitMap(&FolderBitMap,Depth,12,10);
  416.  
  417.                         /* Put the mask into all bitplanes. */
  418.  
  419.                     switch(Type)
  420.                     {
  421.                         case BUTTONIMAGE_FOLDER:
  422.  
  423.                             for(i = 0 ; i < Depth ; i++)
  424.                                 FolderBitMap . Planes[i] = (PLANEPTR)FolderData;
  425.  
  426.                             break;
  427.  
  428.                         case BUTTONIMAGE_FILE:
  429.  
  430.                             for(i = 0 ; i < Depth ; i++)
  431.                                 FolderBitMap . Planes[i] = (PLANEPTR)FileData;
  432.  
  433.                             break;
  434.  
  435.                         case BUTTONIMAGE_SCREEN:
  436.  
  437.                             for(i = 0 ; i < Depth ; i++)
  438.                                 FolderBitMap . Planes[i] = (PLANEPTR)ScreenData;
  439.  
  440.                             break;
  441.                     }
  442.  
  443.                         /* Manipulate the first bitmap. */
  444.  
  445.                     RPort -> BitMap = BitMap[0];
  446.  
  447.                         /* Clear the bitmap. */
  448.  
  449.                     SetRast(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  450.  
  451.                         /* Draw the button box. */
  452.  
  453.                     DrawBevelBox(RPort,0,0,Width,Height,
  454.                         GT_VisualInfo,    VisualInfo,
  455.                     TAG_DONE);
  456.  
  457.                         /* Clear the folder mask. */
  458.  
  459.                     BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,MINTERM_NOT_B_AND_C,(1 << Depth) - 1,NULL);
  460.  
  461.                         /* Draw the folder mask. */
  462.  
  463.                     BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,MINTERM_B_OR_C,DrawInfo -> dri_Pens[TEXTPEN],NULL);
  464.  
  465.                         /* Are we to provide a selecte
  466.                          * image in the new look?
  467.                          */
  468.  
  469.                     if((DrawInfo -> dri_Flags & DRIF_NEWLOOK) && Depth > 1)
  470.                     {
  471.                             /* Manipulate the second bitmap. */
  472.  
  473.                         RPort -> BitMap = BitMap[1];
  474.  
  475.                             /* Set the bitmap to the
  476.                              * selected button colour.
  477.                              */
  478.  
  479.                         SetRast(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  480.  
  481.                             /* Draw the selected button box. */
  482.  
  483.                         DrawBevelBox(RPort,0,0,Width,Height,
  484.                             GTBB_Recessed,    TRUE,
  485.                             GT_VisualInfo,    VisualInfo,
  486.                         TAG_DONE);
  487.  
  488.                             /* Clear the folder mask. */
  489.  
  490.                         BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,MINTERM_NOT_B_AND_C,(1 << Depth) - 1,NULL);
  491.  
  492.                             /* Draw the folder mask. */
  493.  
  494.                         BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,MINTERM_B_OR_C,DrawInfo -> dri_Pens[FILLTEXTPEN],NULL);
  495.                     }
  496.                     else
  497.                     {
  498.                             /* Copy the image. */
  499.  
  500.                         BltBitMap(BitMap[0],0,0,BitMap[1],0,0,Width,Height,MINTERM_COPY,(1 << Depth) - 1,NULL);
  501.  
  502.                             /* Invert the inner area. */
  503.  
  504.                         BltBitMap(BitMap[0],0,0,BitMap[1],2,1,Width - 4,Height - 2,MINTERM_NOT_C,(1 << Depth) - 1,NULL);
  505.                     }
  506.  
  507.                         /* Allocate space for standard image and selected image. */
  508.  
  509.                     if(Image = (struct Image *)AllocVec(2 * sizeof(struct Image),MEMF_ANY | MEMF_CLEAR))
  510.                     {
  511.                             /* Fill in the standard data. */
  512.  
  513.                         for(i = 0 ; i < 2 ; i++)
  514.                         {
  515.                             Image[i] . Width    = Width;
  516.                             Image[i] . Height    = Height;
  517.                             Image[i] . Depth    = Depth;
  518.                             Image[i] . ImageData    = (UWORD *)BitMap[i] -> Planes[0];
  519.                             Image[i] . PlanePick    = (1 << Depth) - 1;
  520.                         }
  521.                     }
  522.  
  523.                         /* Free the screen drawing pen information. */
  524.  
  525.                     FreeScreenDrawInfo(Screen,DrawInfo);
  526.                 }
  527.             }
  528.  
  529.                 /* Free the bitmaps, but not necessarily the
  530.                  * bitplane data.
  531.                  */
  532.  
  533.             for(i = 0 ; i < 2 ; i++)
  534.             {
  535.                 if(BitMap[i])
  536.                 {
  537.                     if(!Success)
  538.                         FreeVec(BitMap[i] -> Planes[0]);
  539.  
  540.                     FreeVec(BitMap[i]);
  541.                 }
  542.             }
  543.  
  544.                 /* Free the rastport. */
  545.  
  546.             FreeVec(RPort);
  547.         }
  548.     }
  549.  
  550.         /* Return the result. */
  551.  
  552.     return(Image);
  553. }
  554.  
  555.     /* NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create):
  556.      *
  557.      *    Prepare a new slider title, padding the label with spaces.
  558.      */
  559.  
  560. STATIC STRPTR __regargs
  561. NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create)
  562. {
  563.     register LONG i,TotalLen,NumSpaces = 0,Last;
  564.  
  565.         /* Determine length of title text. */
  566.  
  567.     TotalLen = Last = strlen(Original);
  568.  
  569.         /* Count the trailing spaces, look for the
  570.          * last character which is not a space.
  571.          */
  572.  
  573.     for(i = TotalLen - 1 ; i >= 0 ; i--)
  574.     {
  575.             /* Is this a space? */
  576.  
  577.         if(Original[i] == ' ')
  578.         {
  579.                 /* Increment number of spaces. */
  580.  
  581.             NumSpaces++;
  582.  
  583.                 /* Remember last space position. */
  584.  
  585.             Last = i;
  586.         }
  587.         else
  588.             break;
  589.     }
  590.  
  591.         /* No spaces? Return the defaults. */
  592.  
  593.     if(!Len && !NumSpaces)
  594.     {
  595.             /* Reset the information. */
  596.  
  597.         if(MaxPixelLen)
  598.             *MaxPixelLen = 0;
  599.  
  600.             /* Return original buffer. */
  601.  
  602.         return(Original);
  603.     }
  604.     else
  605.     {
  606.             /* If no length is given, use the
  607.              * values we have determined. */
  608.  
  609.         if(!Len)
  610.             Len = NumSpaces + 1;
  611.  
  612. /*        if(MaxPixelLen)
  613.             *MaxPixelLen = Len * SZ_MaxNumericWidth;*/
  614.  
  615.         NumSpaces = ((Len - 1) * SZ_MaxNumericWidth) / TextLength(SZ_RPort," ",1) + 1;
  616.  
  617.             /* Copy the body. */
  618.  
  619.         memcpy(SharedBuffer,Original,Last);
  620.  
  621.             /* Supply the spaces if any. */
  622.  
  623.         if(NumSpaces)
  624.             memset(SharedBuffer + Last,' ',NumSpaces);
  625.  
  626.             /* Provide null-termination. */
  627.  
  628.         SharedBuffer[Last + NumSpaces] = 0;
  629.  
  630.             /* Are we to allocate a buffer to
  631.              * hold the new label?
  632.              */
  633.  
  634.         if(Create)
  635.         {
  636.             STRPTR Buffer;
  637.  
  638.                 /* Allocate and copy the buffer. */
  639.  
  640.             if(Buffer = (STRPTR)AllocVec(Last + NumSpaces + 1,MEMF_ANY))
  641.                 strcpy(Buffer,SharedBuffer);
  642.  
  643.                 /* Return the result. */
  644.  
  645.             return(Buffer);
  646.         }
  647.         else
  648.             return(SharedBuffer);
  649.     }
  650. }
  651.  
  652.     /* CreateGadget():
  653.      *
  654.      *    A frontend to the original routine.
  655.      */
  656.  
  657. struct Gadget *
  658. CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...)
  659. {
  660.     STATIC struct NewGadget         Backup;
  661.  
  662.     va_list                 VarArgs;
  663.     struct TagItem            *TagList,
  664.                     *ThisTag,
  665.                      MoreTags[3];
  666.     struct GadgetSupportInfo    *Info = NULL;
  667.     WORD                 i;
  668.     struct Gadget            *Result;
  669.     UWORD                 Flags = NULL;
  670.     STRPTR                 NewGadgetTitle = NULL;
  671.     LONG                 MaxPixelLen = 0;
  672.  
  673.         /* Get the tag item array. */
  674.  
  675.     va_start(VarArgs,New);
  676.  
  677.         /* Make a backup copy of the original NewGadget structure,
  678.          * we may want to modify it.
  679.          */
  680.  
  681.     CopyMem(New,&Backup,sizeof(struct NewGadget));
  682.  
  683.     New = &Backup;
  684.  
  685.         /* Fill in the defaults if none are present. */
  686.  
  687.     if(!New -> ng_VisualInfo)
  688.         New -> ng_VisualInfo = VisualInfo;
  689.  
  690.     if(!New -> ng_TextAttr)
  691.         New -> ng_TextAttr = &UserFont;
  692.  
  693.         /* Get the tag item list. */
  694.  
  695.     TagList = (struct TagItem *)VarArgs;
  696.  
  697.         /* Is this a slider object? */
  698.  
  699.     if(Kind == SLIDER_KIND && New -> ng_GadgetText)
  700.     {
  701.             /* Is a special label width required? */
  702.  
  703.         if(ThisTag = FindTagItem(GTSL_MaxLevelLen,TagList))
  704.             NewGadgetTitle = NewTitle(New -> ng_GadgetText,ThisTag -> ti_Data + 1,&MaxPixelLen,TRUE);
  705.         else
  706.             NewGadgetTitle = NewTitle(New -> ng_GadgetText,0,&MaxPixelLen,TRUE);
  707.     }
  708.  
  709.         /* Try to find the SZ_Adjust tag item. If found, we are to
  710.          * apply our formatting functions to it.
  711.          */
  712.  
  713.     if(ThisTag = FindTagItem(SZ_Adjust,TagList))
  714.     {
  715.         if(ThisTag -> ti_Data)
  716.         {
  717.             LONG     Width,
  718.                  Height,
  719.                  AddHeight    = InterHeight,
  720.                  Left        = SZ_CurrentLeft,
  721.                  Top        = SZ_CurrentTop;
  722.             BYTE     AutoWidth    = FALSE,
  723.                  MoveDown    = TRUE,
  724.                  SaveWidth    = TRUE,
  725.                  SetLeft    = FALSE,
  726.                  SetBelow    = FALSE,
  727.                  DropLeft    = FALSE,
  728.                  DropTop    = FALSE;
  729.  
  730.                 /* Are we to leave the left edge untouched? */
  731.  
  732.             if(ThisTag = FindTagItem(SZ_SaveX,TagList))
  733.                 SetLeft = ThisTag -> ti_Data;
  734.  
  735.                 /* Are we to leave the top edge untouched? */
  736.  
  737.             if(ThisTag = FindTagItem(SZ_SaveY,TagList))
  738.                 SetBelow = ThisTag -> ti_Data;
  739.  
  740.                 /* Are we to use a special inter-object alignment size? */
  741.  
  742.             if(ThisTag = FindTagItem(SZ_InterHeight,TagList))
  743.                 AddHeight = ThisTag -> ti_Data;
  744.  
  745.                 /* Are we to place the new object to the left
  746.                  * of the previous object?
  747.                  */
  748.  
  749.             if(ThisTag = FindTagItem(SZ_PlaceLeft,TagList))
  750.             {
  751.                 if(ThisTag -> ti_Data)
  752.                 {
  753.                     Top        = SZ_LastTop;
  754.                     Left        = SZ_LastLeft + SZ_LastWidth + 2;
  755.  
  756.                     DropLeft    = TRUE;
  757.                     DropTop        = TRUE;
  758.                 }
  759.             }
  760.  
  761.                 /* Are we to place the new object below
  762.                  * the previous object?
  763.                  */
  764.  
  765.             if(ThisTag = FindTagItem(SZ_PlaceBelow,TagList))
  766.             {
  767.                 if(ThisTag -> ti_Data)
  768.                 {
  769.                     Top = SZ_LastTop + SZ_LastHeight + 1;
  770.  
  771.                     DropLeft = TRUE;
  772.                 }
  773.             }
  774.  
  775.                 /* Are we to align the object to the
  776.                  * window bottom?
  777.                  */
  778.  
  779.             if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  780.             {
  781.                 if(ThisTag -> ti_Data)
  782.                     Top = SZ_WindowHeight;
  783.             }
  784.  
  785.                 /* Are we to add extra space to the
  786.                  * object top edge?
  787.                  */
  788.  
  789.             if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  790.             {
  791.                 if(ThisTag -> ti_Data)
  792.                     Top += AddHeight;
  793.             }
  794.  
  795.                 /* Are we to start a new column? */
  796.  
  797.             if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  798.             {
  799.                 if(ThisTag -> ti_Data)
  800.                 {
  801.                     Top        = SZ_Top;
  802.                     Left        = Left + SZ_MaxWidth;
  803.                     SZ_MaxWidth    = 0;
  804.  
  805.                     if(ThisTag = FindTagItem(SZ_SmallSpace,TagList))
  806.                     {
  807.                         if(ThisTag -> ti_Data)
  808.                             Left += 2;
  809.                         else
  810.                             Left += InterWidth;
  811.                     }
  812.                     else
  813.                         Left += InterWidth;
  814.                 }
  815.             }
  816.  
  817.                 /* Is the object to contain a certain
  818.                  * number of lines?
  819.                  */
  820.  
  821.             if(ThisTag = FindTagItem(SZ_Lines,TagList))
  822.             {
  823.                 LONG Lines = (LONG)ThisTag -> ti_Data;
  824.  
  825.                     /* Is it a listview object? */
  826.  
  827.                 if(Kind == LISTVIEW_KIND)
  828.                 {
  829.                         /* Determine height of object. */
  830.  
  831.                     if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  832.                     {
  833.                         if(ThisTag -> ti_Data)
  834.                             Height = SZ_Height(Kind,Lines,SZLV_String);
  835.                         else
  836.                             Height = SZ_Height(Kind,Lines,SZLV_Display);
  837.                     }
  838.                     else
  839.                         Height = SZ_Height(Kind,Lines,NULL);
  840.                 }
  841.                 else
  842.                     Height = SZ_Height(Kind,Lines,NULL);
  843.             }
  844.             else
  845.             {
  846.                     /* If this is a MX kind object,
  847.                      * determine the number of lines
  848.                      * by looking at the labels.
  849.                      */
  850.  
  851.                 if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  852.                 {
  853.                     STRPTR    *Choices;
  854.                     LONG     Lines = 0;
  855.  
  856.                     Choices = (STRPTR *)ThisTag -> ti_Data;
  857.  
  858.                     while(*Choices++)
  859.                         Lines++;
  860.  
  861.                     Height = SZ_Height(Kind,Lines,NULL);
  862.                 }
  863.                 else
  864.                     Height = SZ_Height(Kind,0,NULL);
  865.             }
  866.  
  867.                 /* Is the object width derived from
  868.                  * certain magical calculations or
  869.                  * is it as wide as the default width?
  870.                  */
  871.  
  872.             if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  873.                 AutoWidth = ThisTag -> ti_Data;
  874.  
  875.                 /* Determine the width of the object. */
  876.  
  877.             if(!AutoWidth)
  878.             {
  879.                 STRPTR    *Choices    = NULL,
  880.                      Title        = NULL;
  881.                 LONG     Chars        = 0;
  882.  
  883.                     /* Determine number of characters in
  884.                      * this object.
  885.                      */
  886.  
  887.                 if(ThisTag = FindTagItem(SZ_Chars,TagList))
  888.                     Chars = ThisTag -> ti_Data;
  889.  
  890.                     /* If this is a button object,
  891.                      * calculate the width by looking
  892.                      * at the title.
  893.                      */
  894.  
  895.                 if(Kind == BUTTON_KIND && New -> ng_GadgetText)
  896.                     Title = New -> ng_GadgetText;
  897.  
  898.                     /* If this is a cycle object,
  899.                      * take a look at the labels.
  900.                      */
  901.  
  902.                 if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  903.                     Choices = (STRPTR *)ThisTag -> ti_Data;
  904.  
  905.                     /* If this is a listview object,
  906.                      * take a look at the list.
  907.                      */
  908.  
  909.                 if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  910.                 {
  911.                     if(ThisTag -> ti_Data != ~0)
  912.                     {
  913.                         struct List    *List = (struct List *)ThisTag -> ti_Data;
  914.                         struct Node    *Node;
  915.                         LONG         Len;
  916.  
  917.                         Node = List -> lh_Head;
  918.  
  919.                         while(Node -> ln_Succ)
  920.                         {
  921.                             if((Len = strlen(Node -> ln_Name)) > Chars)
  922.                                 Chars = Len;
  923.  
  924.                             Node = Node -> ln_Succ;
  925.                         }
  926.                     }
  927.                 }
  928.  
  929.                     /* Determine object width. */
  930.  
  931.                 Width = SZ_Width(Kind,Title,Chars,Choices);
  932.             }
  933.             else
  934.             {
  935.                     /* Use the default width. */
  936.  
  937.                 Width = SZ_CurrentWidth;
  938.  
  939.                     /* A checkbox object has a
  940.                      * fixed width. We don't want
  941.                      * any other objects to share
  942.                      * it.
  943.                      */
  944.  
  945.                 if(Kind == CHECKBOX_KIND || Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND)
  946.                 {
  947.                     Width = SZ_Width(Kind,NULL,0,NULL);
  948.  
  949.                     SaveWidth = FALSE;
  950.                 }
  951.             }
  952.  
  953.                 /* Are we to align this object to
  954.                  * the left window edge?
  955.                  */
  956.  
  957.             if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  958.             {
  959.                 if(ThisTag -> ti_Data)
  960.                 {
  961.                     Left = SZ_Left;
  962.  
  963.                     MoveDown = FALSE;
  964.                 }
  965.             }
  966.  
  967.                 /* Are we to use a specific object width? */
  968.  
  969.             if(ThisTag = FindTagItem(SZ_UseWidth,TagList))
  970.                 Width = ThisTag -> ti_Data;
  971.  
  972.                 /* Are we to use a specific object height? */
  973.  
  974.             if(ThisTag = FindTagItem(SZ_UseHeight,TagList))
  975.                 Height = ThisTag -> ti_Data;
  976.  
  977.                 /* Are we to align this object to the
  978.                  * right window edge?
  979.                  */
  980.  
  981.             if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  982.             {
  983.                 if(ThisTag -> ti_Data)
  984.                 {
  985.                     Left = SZ_WindowWidth - INTERWIDTH - Width;
  986.  
  987.                     MoveDown = FALSE;
  988.                 }
  989.             }
  990.  
  991.                 /* Are we to centre the object in
  992.                  * the window?
  993.                  */
  994.  
  995.             if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  996.             {
  997.                 if(ThisTag -> ti_Data)
  998.                 {
  999.                     Left = (SZ_WindowWidth - Width) / 2;
  1000.  
  1001.                     MoveDown = FALSE;
  1002.                 }
  1003.             }
  1004.  
  1005.                 /* Are we to build a horizontal group
  1006.                  * using the following objects?
  1007.                  */
  1008.  
  1009.             if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  1010.             {
  1011.                 LONG    Count = ThisTag -> ti_Data,
  1012.                     Width = SZ_WindowWidth;
  1013.  
  1014.                 if(!Width)
  1015.                     Width = SZ_WindowWidth = SZ_Left + Count * (SZ_CurrentWidth + 2) + InterWidth;
  1016.  
  1017.                 if(!Top)
  1018.                     Top = SZ_Top;
  1019.  
  1020.                     /* Use a specific left edge? */
  1021.  
  1022.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  1023.                 {
  1024.                     Width -= ThisTag -> ti_Data - InterWidth;
  1025.  
  1026.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  1027.                     SZ_GroupX    = Left = ThisTag -> ti_Data;
  1028.                 }
  1029.                 else
  1030.                 {
  1031.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  1032.                     SZ_GroupX    = Left = SZ_Left;
  1033.                 }
  1034.  
  1035.                 MoveDown = FALSE;
  1036.             }
  1037.             else
  1038.             {
  1039.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  1040.                     Left = ThisTag -> ti_Data;
  1041.             }
  1042.  
  1043.                 /* Skip to the next group item position? */
  1044.  
  1045.             if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  1046.             {
  1047.                 if(ThisTag -> ti_Data)
  1048.                 {
  1049.                     SZ_GroupX += SZ_GroupDelta;
  1050.  
  1051.                     Left = SZ_GroupX;
  1052.  
  1053.                     MoveDown = FALSE;
  1054.                 }
  1055.             }
  1056.  
  1057.                 /* Determine default label placement. */
  1058.  
  1059.             switch(Kind)
  1060.             {
  1061.                 case MX_KIND:
  1062.  
  1063.                     New -> ng_Flags    = (New -> ng_Flags & ~(PLACETEXT_LEFT|PLACETEXT_RIGHT|PLACETEXT_ABOVE|PLACETEXT_BELOW|PLACETEXT_IN)) | PLACETEXT_LEFT;
  1064.  
  1065.                     SaveWidth = FALSE;
  1066.  
  1067.                     break;
  1068.  
  1069.                 case CHECKBOX_KIND:
  1070.  
  1071.                     SaveWidth = FALSE;
  1072.                     break;
  1073.  
  1074.                 default:
  1075.  
  1076.                     if(New -> ng_Flags & PLACETEXT_ABOVE)
  1077.                         Top += INTERHEIGHT + SZ_TextFont -> tf_YSize;
  1078.  
  1079.                     break;
  1080.             }
  1081.  
  1082.                 /* Use a specific top edge? */
  1083.  
  1084.             if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  1085.                 Top = ThisTag -> ti_Data;
  1086.  
  1087.                 /* Gadget is to be as wide as the entire window? */
  1088.  
  1089.             if(ThisTag = FindTagItem(SZ_FullWidth,TagList))
  1090.             {
  1091.                 if(ThisTag -> ti_Data)
  1092.                     Width = SZ_WindowWidth - (InterWidth + Left);
  1093.             }
  1094.  
  1095.                 /* Gadget is to be as high as the entire window? */
  1096.  
  1097.             if(ThisTag = FindTagItem(SZ_FullHeight,TagList))
  1098.             {
  1099.                 if(ThisTag -> ti_Data)
  1100.                     Height = SZ_WindowHeight - (AddHeight + SZ_Top + Top);
  1101.             }
  1102.  
  1103.                 /* Leave space for folder icon? */
  1104.  
  1105.             if(ThisTag = FindTagItem(SZ_LeaveFolder,TagList))
  1106.             {
  1107.                 if(ThisTag -> ti_Data && (Kind == STRING_KIND || Kind == PASSWORD_KIND))
  1108.                     New -> ng_Width = Width - (2 + SZ_Width(FOLDER_KIND,"",0,0));
  1109.                 else
  1110.                     New -> ng_Width = Width;
  1111.             }
  1112.             else
  1113.                 New -> ng_Width = Width;
  1114.  
  1115.                 /* Fill in the NewGadget. */
  1116.  
  1117.             New -> ng_LeftEdge    = Left;
  1118.             New -> ng_TopEdge    = Top;
  1119.             New -> ng_Height    = Height;
  1120.  
  1121.                 /* Add the default tags. */
  1122.  
  1123.             switch(Kind)
  1124.             {
  1125. /*                case SLIDER_KIND:
  1126.  
  1127.                     MoreTags[0] . ti_Tag    = GTSL_MaxPixelLen;
  1128.                     MoreTags[0] . ti_Data    = MaxPixelLen;
  1129.  
  1130.                     MoreTags[1] . ti_Tag    = GTSL_Justification;
  1131.                     MoreTags[1] . ti_Data    = GTJ_RIGHT;
  1132.  
  1133.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1134.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1135.  
  1136.                     if(MaxPixelLen)
  1137.                         TagList = MoreTags;
  1138.                     else
  1139.                         TagList = MoreTags + 1;
  1140.  
  1141.                     break;*/
  1142.  
  1143.                 case PALETTE_KIND:
  1144.  
  1145.                     MoreTags[0] . ti_Tag    = GTPA_IndicatorWidth;
  1146.                     MoreTags[0] . ti_Data    = Width / 4;
  1147.  
  1148.                     MoreTags[1] . ti_Tag    = GTPA_IndicatorHeight;
  1149.                     MoreTags[1] . ti_Data    = Height;
  1150.  
  1151.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1152.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1153.  
  1154.                     TagList = MoreTags;
  1155.  
  1156.                     break;
  1157.  
  1158.                 case LISTVIEW_KIND:
  1159.  
  1160.                     MoreTags[0] . ti_Tag    = GTLV_ScrollWidth;
  1161.                     MoreTags[0] . ti_Data    = 2 + 2 * SZ_AverageGlyphWidth + 2;
  1162.  
  1163.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1164.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1165.  
  1166.                     TagList = MoreTags;
  1167.  
  1168.                     break;
  1169.  
  1170.                 case CHECKBOX_KIND:
  1171.  
  1172.                     MoreTags[0] . ti_Tag    = GTCB_Scaled;
  1173.                     MoreTags[0] . ti_Data    = TRUE;
  1174.  
  1175.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1176.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1177.  
  1178.                     TagList = MoreTags;
  1179.  
  1180.                     break;
  1181.  
  1182.                 case MX_KIND:
  1183.  
  1184.                     MoreTags[0] . ti_Tag    = GTMX_Scaled;
  1185.                     MoreTags[0] . ti_Data    = TRUE;
  1186.  
  1187.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1188.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1189.  
  1190.                     TagList = MoreTags;
  1191.  
  1192.                     break;
  1193.  
  1194.                 case STRING_KIND:
  1195.  
  1196.                     MoreTags[0] . ti_Tag    = GTST_EditHook;
  1197.                     MoreTags[0] . ti_Data    = (ULONG)&CommandHook;
  1198.  
  1199.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1200.                     MoreTags[1] . ti_Data    = TRUE;
  1201.  
  1202.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1203.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1204.  
  1205.                     if(!FindTagItem(GTST_EditHook,TagList))
  1206.                         TagList = MoreTags;
  1207.                     else
  1208.                         TagList = MoreTags + 1;
  1209.  
  1210.                     break;
  1211.  
  1212.                 case PASSWORD_KIND:
  1213.  
  1214.                     MoreTags[0] . ti_Tag    = GTST_EditHook;
  1215.                     MoreTags[0] . ti_Data    = (ULONG)&PasswordHook;
  1216.  
  1217.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1218.                     MoreTags[1] . ti_Data    = TRUE;
  1219.  
  1220.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1221.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1222.  
  1223.                     TagList = MoreTags;
  1224.                     break;
  1225.  
  1226.                 case INTEGER_KIND:
  1227.  
  1228.                     MoreTags[0] . ti_Tag    = GTIN_EditHook;
  1229.                     MoreTags[0] . ti_Data    = (ULONG)&CommandHook;
  1230.  
  1231.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1232.                     MoreTags[1] . ti_Data    = TRUE;
  1233.  
  1234.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1235.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1236.  
  1237.                     if(!FindTagItem(GTIN_EditHook,TagList))
  1238.                         TagList = MoreTags;
  1239.                     else
  1240.                         TagList = MoreTags + 1;
  1241.  
  1242.                     break;
  1243.  
  1244.                 case FILE_KIND:
  1245.                 case FOLDER_KIND:
  1246.                 case SCREEN_KIND:
  1247.  
  1248.                     New -> ng_GadgetText = "";
  1249.                     break;
  1250.             }
  1251.  
  1252.                 /* Restore default object width if necessary. */
  1253.  
  1254.             if(SaveWidth)
  1255.                 SZ_CurrentWidth    = Width;
  1256.  
  1257.             if(!DropTop)
  1258.             {
  1259.                     /* Are we to leave the top edge untouched? */
  1260.  
  1261.                 if(SetBelow)
  1262.                 {
  1263.                         /* Extend window height if necessary. */
  1264.  
  1265.                     if(Top + Height + AddHeight > SZ_WindowHeight)
  1266.                         SZ_WindowHeight = Top + Height + AddHeight;
  1267.                 }
  1268.                 else
  1269.                 {
  1270.                     SZ_CurrentTop = Top;
  1271.  
  1272.                     if(MoveDown)
  1273.                     {
  1274.                             /* Move down to next object. */
  1275.  
  1276.                         SZ_CurrentTop = SZ_CurrentTop + Height + AddHeight;
  1277.  
  1278.                             /* Extend window height if necessary. */
  1279.  
  1280.                         if(SZ_CurrentTop > SZ_WindowHeight)
  1281.                             SZ_WindowHeight = SZ_CurrentTop;
  1282.                     }
  1283.                     else
  1284.                     {
  1285.                             /* Extend window height if necessary. */
  1286.  
  1287.                         if(SZ_CurrentTop + Height + AddHeight > SZ_WindowHeight)
  1288.                             SZ_WindowHeight = SZ_CurrentTop + Height + AddHeight;
  1289.  
  1290.                         SZ_MaxWidth = 0;
  1291.                     }
  1292.                 }
  1293.             }
  1294.  
  1295.             if(!DropLeft)
  1296.             {
  1297.                     /* Update maximum object width. */
  1298.  
  1299.                 if(Width > SZ_MaxWidth)
  1300.                     SZ_MaxWidth = Width;
  1301.  
  1302.                     /* Extend window width if necessary. */
  1303.  
  1304.                 if(Left + SZ_MaxWidth + InterWidth > SZ_WindowWidth)
  1305.                     SZ_WindowWidth = Left + SZ_MaxWidth + InterWidth;
  1306.  
  1307.                     /* Are we to leave the left edge untouched? */
  1308.  
  1309.                 if(!SetLeft)
  1310.                     SZ_CurrentLeft = Left;
  1311.             }
  1312.  
  1313.                 /* Remember last object position and size. */
  1314.  
  1315.             SZ_LastLeft    = New -> ng_LeftEdge;
  1316.             SZ_LastWidth    = New -> ng_Width;
  1317.             SZ_LastHeight    = New -> ng_Height;
  1318.  
  1319.             if(New -> ng_Flags & PLACETEXT_ABOVE)
  1320.                 SZ_LastTop = New -> ng_TopEdge - (INTERHEIGHT + SZ_TextFont -> tf_YSize);
  1321.             else
  1322.                 SZ_LastTop = New -> ng_TopEdge;
  1323.         }
  1324.     }
  1325.  
  1326.         /* Now for keystroke activation... */
  1327.  
  1328.     switch(Kind)
  1329.     {
  1330.         case STRING_KIND:
  1331.         case INTEGER_KIND:
  1332.         case BUTTON_KIND:
  1333.         case CHECKBOX_KIND:
  1334.         case CYCLE_KIND:
  1335.         case LISTVIEW_KIND:
  1336.         case MX_KIND:
  1337.         case PALETTE_KIND:
  1338.         case SCROLLER_KIND:
  1339.         case SLIDER_KIND:
  1340.         case PASSWORD_KIND:
  1341.  
  1342.                 /* Do we have a gadget label? */
  1343.  
  1344.             if(New -> ng_GadgetText)
  1345.             {
  1346.                     /* Look for the underscore
  1347.                      * character...
  1348.                      */
  1349.  
  1350.                 for(i = 0 ; i < strlen(New -> ng_GadgetText) ; i++)
  1351.                 {
  1352.                     if(New -> ng_GadgetText[i] == '_')
  1353.                     {
  1354.                             /* Is it a printable character? */
  1355.  
  1356.                         if((WORD)(New -> ng_GadgetText[i + 1]) > ' ')
  1357.                         {
  1358.                                 /* Create information buffer. */
  1359.  
  1360.                             if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
  1361.                             {
  1362.                                 STATIC struct TagItem EvenMoreTags[2];
  1363.  
  1364.                                 EvenMoreTags[0] . ti_Tag    = GT_Underscore;
  1365.                                 EvenMoreTags[0] . ti_Data    = '_';
  1366.  
  1367.                                 EvenMoreTags[1] . ti_Tag    = TAG_MORE;
  1368.                                 EvenMoreTags[1] . ti_Data    = (ULONG)TagList;
  1369.  
  1370.                                 TagList = EvenMoreTags;
  1371.  
  1372.                                     /* Set up the default data. */
  1373.  
  1374.                                 Info -> PointBack    = Info;
  1375.                                 Info -> Kind        = Kind;
  1376.                                 Info -> Key        = New -> ng_GadgetText[i + 1];
  1377.  
  1378.                                     /* Add object-specific information. */
  1379.  
  1380.                                 if(Info -> Kind == PALETTE_KIND)
  1381.                                 {
  1382.                                     Info -> Current    = 1;
  1383.                                     Info -> Max    = 1;
  1384.                                 }
  1385.  
  1386.                                 if(Info -> Kind == LISTVIEW_KIND)
  1387.                                     Info -> Current    = ~0;
  1388.  
  1389.                                 break;
  1390.                             }
  1391.                         }
  1392.                     }
  1393.                 }
  1394.             }
  1395.  
  1396.             break;
  1397.  
  1398.         default:
  1399.  
  1400.             break;
  1401.     }
  1402.  
  1403.         /* No GadgetInfo supplied yet? Does this object need any? */
  1404.  
  1405.     if(!Info && (Kind == PASSWORD_KIND || Kind == FILE_KIND || Kind == FOLDER_KIND || Kind == SCREEN_KIND || Flags || NewGadgetTitle))
  1406.     {
  1407.             /* Allocate GadgetInfo. */
  1408.  
  1409.         if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
  1410.         {
  1411.             Info -> PointBack    = Info;
  1412.             Info -> Kind        = Kind;
  1413.         }
  1414.     }
  1415.  
  1416.         /* Fill in object info if available. */
  1417.  
  1418.     New -> ng_UserData = Info;
  1419.  
  1420.         /* Fill in the new title if available. */
  1421.  
  1422.     if(NewGadgetTitle)
  1423.         New -> ng_GadgetText = NewGadgetTitle;
  1424.  
  1425.         /* Did we create any object info? */
  1426.  
  1427.     if(Info)
  1428.     {
  1429.         struct Node    *Node;
  1430.         struct List    *List;
  1431.         LONG         Count;
  1432.         STRPTR        *Strings;
  1433.         struct TagItem    *NewTagList;
  1434.  
  1435.             /* The following code takes care of object-specific
  1436.              * characteristics, such as currently selected items,
  1437.              * current value, minimum value, maximum value, etc.
  1438.              * and places them in the gadget info.
  1439.              */
  1440.  
  1441.         switch(Kind)
  1442.         {
  1443.             case CHECKBOX_KIND:
  1444.  
  1445.                 if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  1446.                     Info -> Current = ThisTag -> ti_Data;
  1447.  
  1448.                 break;
  1449.  
  1450.             case CYCLE_KIND:
  1451.  
  1452.                 if(ThisTag = FindTagItem(GTCY_Active,TagList))
  1453.                     Info -> Current = ThisTag -> ti_Data;
  1454.  
  1455.                 if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  1456.                 {
  1457.                     Count = 0;
  1458.  
  1459.                     if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1460.                     {
  1461.                         while(Strings[Count])
  1462.                             Count++;
  1463.                     }
  1464.  
  1465.                     if(Count)
  1466.                         Info -> Max = Count - 1;
  1467.                 }
  1468.  
  1469.                 break;
  1470.  
  1471.             case LISTVIEW_KIND:
  1472.  
  1473.                 if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  1474.                     Info -> Current = ThisTag -> ti_Data;
  1475.  
  1476.                 if(ThisTag = FindTagItem(GTLV_ReadOnly,TagList))
  1477.                 {
  1478.                     if(ThisTag -> ti_Data)
  1479.                         Info -> ReadOnly = TRUE;
  1480.                 }
  1481.  
  1482.                 if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  1483.                 {
  1484.                     if(ThisTag -> ti_Data)
  1485.                         Info -> ReadOnly = FALSE;
  1486.                 }
  1487.  
  1488.                 if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1489.                 {
  1490.                     Count = 0;
  1491.  
  1492.                     if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1493.                     {
  1494.                         List = (struct List *)ThisTag -> ti_Data;
  1495.  
  1496.                         Node = List -> lh_Head;
  1497.  
  1498.                         while(Node -> ln_Succ)
  1499.                         {
  1500.                             Count++;
  1501.  
  1502.                             Node = Node -> ln_Succ;
  1503.                         }
  1504.                     }
  1505.  
  1506.                     if(Count)
  1507.                         Info -> Max = Count - 1;
  1508.                 }
  1509.  
  1510.                 break;
  1511.  
  1512.             case MX_KIND:
  1513.  
  1514.                 if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1515.                     Info -> Current = ThisTag -> ti_Data;
  1516.  
  1517.                 if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  1518.                 {
  1519.                     Count = 0;
  1520.  
  1521.                     if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1522.                     {
  1523.                         while(Strings[Count])
  1524.                             Count++;
  1525.                     }
  1526.  
  1527.                     if(Count)
  1528.                         Info -> Max = Count - 1;
  1529.                 }
  1530.  
  1531.                 break;
  1532.  
  1533.             case SCROLLER_KIND:
  1534.  
  1535.                 if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1536.                     Info -> Current = ThisTag -> ti_Data;
  1537.  
  1538.                 if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1539.                     Info -> Max = ThisTag -> ti_Data;
  1540.  
  1541.                 break;
  1542.  
  1543.             case SLIDER_KIND:
  1544.  
  1545.                 if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1546.                     Info -> Current = ThisTag -> ti_Data;
  1547.  
  1548.                 if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1549.                     Info -> Min = ThisTag -> ti_Data;
  1550.  
  1551.                 if(ThisTag = FindTagItem(GTSL_Max,TagList))
  1552.                     Info -> Max = ThisTag -> ti_Data;
  1553.  
  1554.                 break;
  1555.  
  1556.             case PALETTE_KIND:
  1557.  
  1558.                 if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1559.                     Info -> Current = ThisTag -> ti_Data;
  1560.  
  1561.                 if(ThisTag = FindTagItem(GTPA_Depth,TagList))
  1562.                     Info -> Max = (1 << ((LONG)ThisTag -> ti_Data)) - 1;
  1563.  
  1564.                 break;
  1565.         }
  1566.  
  1567.             /* In order to avoid collisions with system software tags,
  1568.              * we will clone the current tag item list and filter
  1569.              * our private tags out before surrendering it to
  1570.              * CreateGadget().
  1571.              */
  1572.  
  1573.         if(NewTagList = CloneTagItems(TagList))
  1574.         {
  1575.                 /* Remove the private tags. */
  1576.  
  1577.             FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
  1578.  
  1579.                 /* Are we to create a custom button object? */
  1580.  
  1581.             if(Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND)
  1582.             {
  1583.                 BYTE Type;
  1584.  
  1585.                     /* Which kind of object are we to create? */
  1586.  
  1587.                 switch(Kind)
  1588.                 {
  1589.                     case FOLDER_KIND:
  1590.  
  1591.                         Type = BUTTONIMAGE_FOLDER;
  1592.                         break;
  1593.  
  1594.                     case FILE_KIND:
  1595.  
  1596.                         Type = BUTTONIMAGE_FILE;
  1597.                         break;
  1598.  
  1599.                     case SCREEN_KIND:
  1600.  
  1601.                         Type = BUTTONIMAGE_SCREEN;
  1602.                         break;
  1603.                 }
  1604.  
  1605.                     /* Create the images. */
  1606.  
  1607.                 if(Info -> Image = CreateButtonImages(Type,New -> ng_Width,New -> ng_Height,SZ_Screen,VisualInfo))
  1608.                 {
  1609.                         /* Create the object and attach the info to it. */
  1610.  
  1611.                     if(Result = OldCreateGadgetA(GENERIC_KIND,Previous,New,NewTagList))
  1612.                     {
  1613.                         Result -> GadgetType    |= GTYP_BOOLGADGET;
  1614.                         Result -> GadgetRender     = &Info -> Image[0];
  1615.                         Result -> SelectRender     = &Info -> Image[1];
  1616.                         Result -> Flags        |= GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
  1617.                         Result -> Activation    |= GACT_RELVERIFY;
  1618.                     }
  1619.                 }
  1620.                 else
  1621.                     Result = NULL;
  1622.             }
  1623.             else
  1624.             {
  1625.                     /* Are we to create a password entry string gadget? */
  1626.  
  1627.                 if(Kind == PASSWORD_KIND)
  1628.                 {
  1629.                     LONG MaxChars = 0;
  1630.  
  1631.                         /* Determine number of characters
  1632.                          * the gadget is to hold.
  1633.                          */
  1634.  
  1635.                     if(ThisTag = FindTagItem(GTST_MaxChars,NewTagList))
  1636.                         MaxChars = ThisTag -> ti_Data;
  1637.  
  1638.                         /* Any size set? */
  1639.  
  1640.                     if(MaxChars)
  1641.                     {
  1642.                             /* Allocate the auxilary buffers. */
  1643.  
  1644.                         if(Info -> Original = (STRPTR)AllocVec((MaxChars + 2) * 2,MEMF_PUBLIC|MEMF_CLEAR))
  1645.                         {
  1646.                                 /* Set up the text entry buffer. */
  1647.  
  1648.                             Info -> Buffer = Info -> Original + (MaxChars + 2);
  1649.  
  1650.                                 /* If available find the original
  1651.                                  * string this gadget is to be
  1652.                                  * preset with.
  1653.                                  */
  1654.  
  1655.                             if(ThisTag = FindTagItem(GTST_String,NewTagList))
  1656.                             {
  1657.                                 LONG Len;
  1658.  
  1659.                                     /* Remember the original data. */
  1660.  
  1661.                                 strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
  1662.                                 strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
  1663.  
  1664.                                     /* Determine length of the original text. */
  1665.  
  1666.                                 Len = strlen(Info -> Original);
  1667.  
  1668.                                     /* Provide fake input. */
  1669.  
  1670.                                 memset(SharedBuffer,'*',Len);
  1671.  
  1672.                                 SharedBuffer[Len] = 0;
  1673.  
  1674.                                     /* This is our own private tag item
  1675.                                      * list, so why bother.
  1676.                                      */
  1677.  
  1678.                                 ThisTag -> ti_Data = (ULONG)SharedBuffer;
  1679.                             }
  1680.  
  1681.                             Result = OldCreateGadgetA(STRING_KIND,Previous,New,NewTagList);
  1682.                         }
  1683.                         else
  1684.                             Result = NULL;
  1685.                     }
  1686.                     else
  1687.                         Result = NULL;
  1688.                 }
  1689.                 else
  1690.                 {
  1691.                         /* Create the object and attach the info to it. */
  1692.  
  1693.                     Result = OldCreateGadgetA(Kind,Previous,New,NewTagList);
  1694.                 }
  1695.             }
  1696.  
  1697.                 /* Successful? */
  1698.  
  1699.             if(Result)
  1700.             {
  1701.                     /* Fill in the data. */
  1702.  
  1703.                 Info -> Gadget    = Result;
  1704.                 Info -> Flags    = Flags;
  1705.                 Info -> Title    = NewGadgetTitle;
  1706.             }
  1707.             else
  1708.             {
  1709.                     /* Free the images. */
  1710.  
  1711.                 if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND || Info -> Kind == SCREEN_KIND))
  1712.                 {
  1713.                     WORD i;
  1714.  
  1715.                     for(i = 0 ; i < 2 ; i++)
  1716.                         FreeVec(Info -> Image[i] . ImageData);
  1717.  
  1718.                     FreeVec(Info -> Image);
  1719.                 }
  1720.  
  1721.                     /* Free the password gadget buffers. */
  1722.  
  1723.                 if(Info -> Original && Info -> Kind == PASSWORD_KIND)
  1724.                     FreeVec(Info -> Original);
  1725.  
  1726.                     /* Free alternative gadget label. */
  1727.  
  1728.                 if(NewGadgetTitle)
  1729.                     FreeVec(NewGadgetTitle);
  1730.  
  1731.                     /* Free the info buffer itself. */
  1732.  
  1733.                 FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1734.             }
  1735.  
  1736.                 /* Free the private tag item list. */
  1737.  
  1738.             FreeTagItems(NewTagList);
  1739.         }
  1740.         else
  1741.         {
  1742.                 /* Free alternative gadget label. */
  1743.  
  1744.             if(NewGadgetTitle)
  1745.                 FreeVec(NewGadgetTitle);
  1746.  
  1747.                 /* Free the info buffer itself. */
  1748.  
  1749.             FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1750.  
  1751.             Result = NULL;
  1752.         }
  1753.     }
  1754.     else
  1755.     {
  1756.             /* No private objects, please. */
  1757.  
  1758.         if(Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND || Kind == PASSWORD_KIND)
  1759.             Result = NULL;
  1760.         else
  1761.         {
  1762.             struct TagItem *NewTagList;
  1763.  
  1764.                 /* Copy the tag item list. */
  1765.  
  1766.             if(NewTagList = CloneTagItems(TagList))
  1767.             {
  1768.                     /* Filter out the private tags if any. */
  1769.  
  1770.                 FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
  1771.  
  1772.                     /* Create the object. */
  1773.  
  1774.                 Result = OldCreateGadgetA(Kind,Previous,New,TagList);
  1775.  
  1776.                     /* Free the private tag item list. */
  1777.  
  1778.                 FreeTagItems(NewTagList);
  1779.             }
  1780.         }
  1781.     }
  1782.  
  1783.     va_end(VarArgs);
  1784.  
  1785.         /* Patch in the GACT_IMMEDIATE flag for string gadget objects under
  1786.          * v37. Although this does not look very clean it is temporarily
  1787.          * permitted for this single release.
  1788.          */
  1789.  
  1790.     if(Result && GadToolsBase -> lib_Version == 37 && (Kind == STRING_KIND || Kind == INTEGER_KIND || Kind == PASSWORD_KIND))
  1791.         Result -> Activation |= GACT_IMMEDIATE;
  1792.  
  1793.     return(Result);
  1794. }
  1795.  
  1796.     /* GT_SetGadgetAttrs():
  1797.      *
  1798.      *    A frontend to the original routine.
  1799.      */
  1800.  
  1801. VOID
  1802. GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...)
  1803. {
  1804.     va_list                 VarArgs;
  1805.     struct TagItem            *TagList,
  1806.                     *ThisTag;
  1807.     struct GadgetSupportInfo    *Info;
  1808.  
  1809.         /* Get the tag item list. */
  1810.  
  1811.     va_start(VarArgs,Requester);
  1812.  
  1813.     TagList = (struct TagItem *)VarArgs;
  1814.  
  1815.         /* Does the object in question have an info structure attached? */
  1816.  
  1817.     if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1818.     {
  1819.             /* Does the data look sensible? */
  1820.  
  1821.         if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1822.         {
  1823.             struct Node    *Node;
  1824.             struct List    *List;
  1825.             LONG         Count;
  1826.             STRPTR        *Strings;
  1827.  
  1828.                 /* Update object-specific information. */
  1829.  
  1830.             switch(Info -> Kind)
  1831.             {
  1832.                 case CHECKBOX_KIND:
  1833.  
  1834.                     if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  1835.                         Info -> Current = ThisTag -> ti_Data;
  1836.  
  1837.                     break;
  1838.  
  1839.                 case CYCLE_KIND:
  1840.  
  1841.                     if(ThisTag = FindTagItem(GTCY_Active,TagList))
  1842.                         Info -> Current = ThisTag -> ti_Data;
  1843.  
  1844.                     if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  1845.                     {
  1846.                         Count = 0;
  1847.  
  1848.                         if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1849.                         {
  1850.                             while(Strings[Count])
  1851.                                 Count++;
  1852.                         }
  1853.  
  1854.                         if(Count)
  1855.                             Info -> Max = Count - 1;
  1856.                         else
  1857.                             Info -> Max = 0;
  1858.                     }
  1859.  
  1860.                     break;
  1861.  
  1862.                 case LISTVIEW_KIND:
  1863.  
  1864.                     if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  1865.                         Info -> Current = ThisTag -> ti_Data;
  1866.  
  1867.                     if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1868.                     {
  1869.                         Count = 0;
  1870.  
  1871.                         if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1872.                         {
  1873.                             List = (struct List *)ThisTag -> ti_Data;
  1874.  
  1875.                             Node = List -> lh_Head;
  1876.  
  1877.                             while(Node -> ln_Succ)
  1878.                             {
  1879.                                 Count++;
  1880.  
  1881.                                 Node = Node -> ln_Succ;
  1882.                             }
  1883.                         }
  1884.  
  1885.                         if(Count)
  1886.                             Info -> Max = Count - 1;
  1887.                         else
  1888.                             Info -> Max = 0;
  1889.                     }
  1890.  
  1891.                     break;
  1892.  
  1893.                 case PALETTE_KIND:
  1894.  
  1895.                     if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1896.                         Info -> Current = ThisTag -> ti_Data;
  1897.  
  1898.                     break;
  1899.  
  1900.                 case MX_KIND:
  1901.  
  1902.                     if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1903.                         Info -> Current = ThisTag -> ti_Data;
  1904.  
  1905.                     break;
  1906.  
  1907.                 case SCROLLER_KIND:
  1908.  
  1909.                     if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1910.                         Info -> Current = ThisTag -> ti_Data;
  1911.  
  1912.                     if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1913.                         Info -> Max = ThisTag -> ti_Data;
  1914.  
  1915.                     break;
  1916.  
  1917.                 case SLIDER_KIND:
  1918.  
  1919.                     if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1920.                         Info -> Current = ThisTag -> ti_Data;
  1921.  
  1922.                     if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1923.                         Info -> Min = ThisTag -> ti_Data;
  1924.  
  1925.                     break;
  1926.  
  1927.                 case PASSWORD_KIND:
  1928.  
  1929.                     if(FindTagItem(GTST_String,TagList))
  1930.                     {
  1931.                         struct TagItem *NewTagList;
  1932.  
  1933.                         if(NewTagList = CloneTagItems(TagList))
  1934.                         {
  1935.                             LONG Len;
  1936.  
  1937.                             ThisTag = FindTagItem(GTST_String,NewTagList);
  1938.  
  1939.                             Forbid();
  1940.  
  1941.                             strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
  1942.                             strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
  1943.  
  1944.                             Len = strlen(Info -> Buffer);
  1945.  
  1946.                             memset(SharedBuffer,'*',Len);
  1947.  
  1948.                             SharedBuffer[Len] = 0;
  1949.  
  1950.                             ThisTag -> ti_Data = (ULONG)SharedBuffer;
  1951.  
  1952.                             OldGT_SetGadgetAttrsA(Gadget,Window,Requester,NewTagList);
  1953.  
  1954.                             FreeTagItems(NewTagList);
  1955.  
  1956.                             Permit();
  1957.                         }
  1958.  
  1959.                         va_end(VarArgs);
  1960.  
  1961.                         return;
  1962.                     }
  1963.  
  1964.                     break;
  1965.             }
  1966.         }
  1967.     }
  1968.  
  1969.         /* Call the original routine. */
  1970.  
  1971.     OldGT_SetGadgetAttrsA(Gadget,Window,Requester,TagList);
  1972.  
  1973.     va_end(VarArgs);
  1974. }
  1975.  
  1976.     /* FreeGadgets(struct Gadget *GadgetList):
  1977.      *
  1978.      *    A frontend to the original routine.
  1979.      */
  1980.  
  1981. VOID
  1982. FreeGadgets(struct Gadget *GadgetList)
  1983. {
  1984.     struct Gadget            *Gadget = GadgetList;
  1985.     struct GadgetSupportInfo    *Info;
  1986.  
  1987.         /* Run down the gadget list. */
  1988.  
  1989.     while(Gadget)
  1990.     {
  1991.             /* Is this the previously active string gadget? */
  1992.  
  1993.         if(Gadget == ActiveGadget)
  1994.             ActiveGadget = NULL;
  1995.  
  1996.             /* Does it have an info structure attached?*/
  1997.  
  1998.         if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1999.         {
  2000.                 /* Does the data make sense? */
  2001.  
  2002.             if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  2003.             {
  2004.                 if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND || Info -> Kind == SCREEN_KIND))
  2005.                 {
  2006.                     WORD i;
  2007.  
  2008.                     for(i = 0 ; i < 2 ; i++)
  2009.                         FreeVec(Info -> Image[i] . ImageData);
  2010.  
  2011.                     FreeVec(Info -> Image);
  2012.                 }
  2013.  
  2014.                 if(Info -> Original && Info -> Kind == PASSWORD_KIND)
  2015.                     FreeVec(Info -> Original);
  2016.  
  2017.                 if(Info -> Title)
  2018.                     FreeVec(Info -> Title);
  2019.  
  2020.                 FreeMem(Info,sizeof(struct GadgetSupportInfo));
  2021.             }
  2022.         }
  2023.  
  2024.             /* Skip to next object. */
  2025.  
  2026.         Gadget = Gadget -> NextGadget;
  2027.     }
  2028.  
  2029.     OldFreeGadgets(GadgetList);
  2030. }
  2031.  
  2032.     /* GT_ReplyIMsg(struct IntuiMessage *Message):
  2033.      *
  2034.      *    A frontend to the original routine.
  2035.      */
  2036.  
  2037. VOID
  2038. GT_ReplyIMsg(struct IntuiMessage *Message)
  2039. {
  2040.         /* Is this really a message? */
  2041.  
  2042.     if(Message)
  2043.     {
  2044.             /* The following input event classes are likely to
  2045.              * affect a gadtools object.
  2046.              */
  2047.  
  2048.         if(Message -> Class == IDCMP_GADGETUP || Message -> Class == IDCMP_GADGETDOWN || Message -> Class == IDCMP_MOUSEMOVE)
  2049.         {
  2050.             struct Gadget *Gadget;
  2051.  
  2052.                 /* Take a look at the item attached. */
  2053.  
  2054.             if(Gadget = (struct Gadget *)Message -> IAddress)
  2055.             {
  2056.                 struct GadgetSupportInfo *Info = Gadget -> UserData;
  2057.  
  2058.                     /* If it's really a gadget, does it
  2059.                      * have an info structure attached?
  2060.                      */
  2061.  
  2062.                 if(Info)
  2063.                 {
  2064.                         /* Does the data make sense? */
  2065.  
  2066.                     if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  2067.                     {
  2068.                         LONG Value = (WORD)Message -> Code;
  2069.  
  2070.                             /* Update the object information. */
  2071.  
  2072.                         switch(Info -> Kind)
  2073.                         {
  2074.                             case CHECKBOX_KIND:
  2075.  
  2076.                                 if(Gadget -> Flags & GFLG_SELECTED)
  2077.                                     Info -> Current = TRUE;
  2078.                                 else
  2079.                                     Info -> Current = FALSE;
  2080.  
  2081.                                 break;
  2082.  
  2083.                             case CYCLE_KIND:
  2084.  
  2085.                                 Info -> Current = Message -> Code;
  2086.  
  2087.                                 break;
  2088.  
  2089.                             case LISTVIEW_KIND:
  2090.  
  2091.                                 Info -> Current = Message -> Code;
  2092.  
  2093.                                 break;
  2094.  
  2095.                             case MX_KIND:
  2096.  
  2097.                                 Info -> Current = Message -> Code;
  2098.  
  2099.                                 break;
  2100.  
  2101.                             case SCROLLER_KIND:
  2102.  
  2103.                                 Info -> Current = Message -> Code;
  2104.  
  2105.                                 break;
  2106.  
  2107.                             case SLIDER_KIND:
  2108.  
  2109.                                 if(Info -> Min >= 0 && Value < 0)
  2110.                                     Info -> Current = Message -> Code;
  2111.                                 else
  2112.                                     Info -> Current = Value;
  2113.  
  2114.                                 break;
  2115.  
  2116.                             case PALETTE_KIND:
  2117.  
  2118.                                 Info -> Current = Message -> Code;
  2119.  
  2120.                                 break;
  2121.  
  2122.                             default:
  2123.  
  2124.                                 break;
  2125.                         }
  2126.                     }
  2127.                 }
  2128.             }
  2129.         }
  2130.     }
  2131.  
  2132.         /* Reply the message correctly. */
  2133.  
  2134.     OldGT_ReplyIMsg(Message);
  2135. }
  2136.  
  2137.     /* KeySelect():
  2138.      *
  2139.      *    Handles gadget keystroke activation.
  2140.      */
  2141.  
  2142. VOID
  2143. KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code)
  2144. {
  2145.     if(*IClass == IDCMP_VANILLAKEY)
  2146.     {
  2147.             /* If an escape code comes in and the window does in
  2148.              * fact have a close gadget, return a close window
  2149.              * event.
  2150.              */
  2151.  
  2152.         if(Key == '\033' && (Window -> Flags & WFLG_CLOSEGADGET))
  2153.             *IClass = IDCMP_CLOSEWINDOW;
  2154.         else
  2155.         {
  2156.             struct GadgetSupportInfo    *Info;
  2157.             WORD                 i;
  2158.             BYTE                 Forward,
  2159.                              GotIt = FALSE;
  2160.  
  2161.                 /* Run down all the gadgets. */
  2162.  
  2163.             for(i = 0 ; !GotIt && i <= Last ; i++)
  2164.             {
  2165.                     /* Is there a gadget? */
  2166.  
  2167.                 if(GadgetList[i])
  2168.                 {
  2169.                         /* Is this gadget enabled? */
  2170.  
  2171.                     if(!(GadgetList[i] -> Flags & GFLG_DISABLED))
  2172.                     {
  2173.                             /* Does it have an info structure attached? */
  2174.  
  2175.                         if(Info = GadgetList[i] -> UserData)
  2176.                         {
  2177.                                 /* Does it make sense? */
  2178.  
  2179.                             if(Info -> PointBack == Info && Info -> Gadget == GadgetList[i])
  2180.                             {
  2181.                                     /* Do the keys match? */
  2182.  
  2183.                                 if(ToUpper(Info -> Key) == ToUpper(Key))
  2184.                                 {
  2185.                                         /* Are we cycle forward
  2186.                                          * or backwards?
  2187.                                          */
  2188.  
  2189.                                     if(ToUpper(Info -> Key) == Key)
  2190.                                         Forward = FALSE;
  2191.                                     else
  2192.                                         Forward = TRUE;
  2193.  
  2194.                                         /* Update the object information. */
  2195.  
  2196.                                     switch(Info -> Kind)
  2197.                                     {
  2198.                                         case PASSWORD_KIND:
  2199.                                         case STRING_KIND:
  2200.                                         case INTEGER_KIND:
  2201.  
  2202.                                             ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  2203.  
  2204.                                             *IClass    = IDCMP_GADGETDOWN;
  2205.                                             *Code    = 0;
  2206.                                             *Gadget    = GadgetList[i];
  2207.  
  2208.                                             GotIt = TRUE;
  2209.  
  2210.                                             break;
  2211.  
  2212.                                         case BUTTON_KIND:
  2213.  
  2214.                                             *IClass    = IDCMP_GADGETUP;
  2215.                                             *Code    = 0;
  2216.                                             *Gadget    = GadgetList[i];
  2217.  
  2218.                                             GotIt = TRUE;
  2219.  
  2220.                                             break;
  2221.  
  2222.                                         case CHECKBOX_KIND:
  2223.  
  2224.                                             GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2225.                                                 GTCB_Checked,    Info -> Current ? FALSE : TRUE,
  2226.                                             TAG_DONE);
  2227.  
  2228.                                             *IClass    = IDCMP_GADGETUP;
  2229.                                             *Code    = Info -> Current;
  2230.                                             *Gadget    = GadgetList[i];
  2231.  
  2232.                                             GotIt = TRUE;
  2233.  
  2234.                                             break;
  2235.  
  2236.                                         case CYCLE_KIND:
  2237.  
  2238.                                             if(Forward)
  2239.                                             {
  2240.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2241.                                                     GTCY_Active,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  2242.                                                 TAG_DONE);
  2243.                                             }
  2244.                                             else
  2245.                                             {
  2246.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2247.                                                     GTCY_Active,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  2248.                                                 TAG_DONE);
  2249.                                             }
  2250.  
  2251.                                             *IClass    = IDCMP_GADGETUP;
  2252.                                             *Code    = Info -> Current;
  2253.                                             *Gadget    = GadgetList[i];
  2254.  
  2255.                                             GotIt = TRUE;
  2256.  
  2257.                                             break;
  2258.  
  2259.                                         case LISTVIEW_KIND:
  2260.  
  2261.                                             if(Forward)
  2262.                                             {
  2263.                                                 if(Info -> Current == ~0)
  2264.                                                     Info -> Current = -1;
  2265.  
  2266.                                                 if(Info -> Current < Info -> Max)
  2267.                                                 {
  2268.                                                     if(Info -> ReadOnly)
  2269.                                                     {
  2270.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2271.                                                             GTLV_Top,        Info -> Current + 1,
  2272.                                                             GTLV_MakeVisible,    Info -> Current + 1,
  2273.                                                         TAG_DONE);
  2274.                                                     }
  2275.                                                     else
  2276.                                                     {
  2277.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2278.                                                             GTLV_Selected,        Info -> Current + 1,
  2279.                                                             GTLV_Top,        Info -> Current + 1,
  2280.                                                             GTLV_MakeVisible,    Info -> Current + 1,
  2281.                                                         TAG_DONE);
  2282.                                                     }
  2283.  
  2284.                                                     *IClass    = IDCMP_GADGETUP;
  2285.                                                     *Code    = Info -> Current;
  2286.                                                     *Gadget    = GadgetList[i];
  2287.                                                 }
  2288.                                             }
  2289.                                             else
  2290.                                             {
  2291.                                                 if(Info -> Current == ~0)
  2292.                                                     Info -> Current = Info -> Max + 1;
  2293.  
  2294.                                                 if(Info -> Current > Info -> Min)
  2295.                                                 {
  2296.                                                     if(Info -> ReadOnly)
  2297.                                                     {
  2298.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2299.                                                             GTLV_Top,        Info -> Current - 1,
  2300.                                                             GTLV_MakeVisible,    Info -> Current - 1,
  2301.                                                         TAG_DONE);
  2302.                                                     }
  2303.                                                     else
  2304.                                                     {
  2305.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2306.                                                             GTLV_Selected,        Info -> Current - 1,
  2307.                                                             GTLV_Top,        Info -> Current - 1,
  2308.                                                             GTLV_MakeVisible,    Info -> Current - 1,
  2309.                                                         TAG_DONE);
  2310.                                                     }
  2311.  
  2312.                                                     *IClass    = IDCMP_GADGETUP;
  2313.                                                     *Code    = Info -> Current;
  2314.                                                     *Gadget    = GadgetList[i];
  2315.                                                 }
  2316.                                             }
  2317.  
  2318.                                             GotIt = TRUE;
  2319.  
  2320.                                             break;
  2321.  
  2322.                                         case MX_KIND:
  2323.  
  2324.                                             if(Forward)
  2325.                                             {
  2326.                                                 if(Info -> Current < Info -> Max)
  2327.                                                 {
  2328.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2329.                                                         GTMX_Active,    *Code = Info -> Current + 1,
  2330.                                                     TAG_DONE);
  2331.  
  2332.                                                     *IClass    = IDCMP_GADGETUP;
  2333.                                                     *Code    = Info -> Current;
  2334.                                                     *Gadget    = GadgetList[i];
  2335.                                                 }
  2336.                                             }
  2337.                                             else
  2338.                                             {
  2339.                                                 if(Info -> Current > Info -> Min)
  2340.                                                 {
  2341.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2342.                                                         GTMX_Active,    *Code = Info -> Current - 1,
  2343.                                                     TAG_DONE);
  2344.  
  2345.                                                     *IClass    = IDCMP_GADGETUP;
  2346.                                                     *Code    = Info -> Current;
  2347.                                                     *Gadget    = GadgetList[i];
  2348.                                                 }
  2349.                                             }
  2350.  
  2351.                                             GotIt = TRUE;
  2352.  
  2353.                                             break;
  2354.  
  2355.                                         case PALETTE_KIND:
  2356.  
  2357.                                             if(Forward)
  2358.                                             {
  2359.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2360.                                                     GTPA_Color,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  2361.                                                 TAG_DONE);
  2362.                                             }
  2363.                                             else
  2364.                                             {
  2365.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2366.                                                     GTPA_Color,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  2367.                                                 TAG_DONE);
  2368.                                             }
  2369.  
  2370.                                             *IClass    = IDCMP_GADGETUP;
  2371.                                             *Code    = Info -> Current;
  2372.                                             *Gadget    = GadgetList[i];
  2373.  
  2374.                                             GotIt = TRUE;
  2375.  
  2376.                                             break;
  2377.  
  2378.                                         case SCROLLER_KIND:
  2379.  
  2380.                                             if(Forward)
  2381.                                             {
  2382.                                                 if(Info -> Current < Info -> Max)
  2383.                                                 {
  2384.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2385.                                                         GTSC_Top,    Info -> Current + 1,
  2386.                                                     TAG_DONE);
  2387.  
  2388.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2389.                                                     *Code    = Info -> Current;
  2390.                                                     *Gadget    = GadgetList[i];
  2391.                                                 }
  2392.                                             }
  2393.                                             else
  2394.                                             {
  2395.                                                 if(Info -> Current > Info -> Min)
  2396.                                                 {
  2397.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2398.                                                         GTSC_Top,    Info -> Current - 1,
  2399.                                                     TAG_DONE);
  2400.  
  2401.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2402.                                                     *Code    = Info -> Current;
  2403.                                                     *Gadget    = GadgetList[i];
  2404.                                                 }
  2405.                                             }
  2406.  
  2407.                                             GotIt = TRUE;
  2408.  
  2409.                                             break;
  2410.  
  2411.                                         case SLIDER_KIND:
  2412.  
  2413.                                             if(Forward)
  2414.                                             {
  2415.                                                 if(Info -> Current < Info -> Max)
  2416.                                                 {
  2417.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2418.                                                         GTSL_Level,    Info -> Current + 1,
  2419.                                                     TAG_DONE);
  2420.  
  2421.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2422.                                                     *Code    = Info -> Current;
  2423.                                                     *Gadget    = GadgetList[i];
  2424.                                                 }
  2425.                                             }
  2426.                                             else
  2427.                                             {
  2428.                                                 if(Info -> Current > Info -> Min)
  2429.                                                 {
  2430.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2431.                                                         GTSL_Level,    Info -> Current - 1,
  2432.                                                     TAG_DONE);
  2433.  
  2434.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2435.                                                     *Code    = Info -> Current;
  2436.                                                     *Gadget    = GadgetList[i];
  2437.                                                 }
  2438.                                             }
  2439.  
  2440.                                             GotIt = TRUE;
  2441.  
  2442.                                             break;
  2443.                                     }
  2444.                                 }
  2445.                             }
  2446.                         }
  2447.                     }
  2448.                 }
  2449.             }
  2450.  
  2451.                 /* If no matching object was found, take a closer look at the types. */
  2452.  
  2453.             if(!GotIt)
  2454.             {
  2455.                 for(i = 0 ; i <= Last ; i++)
  2456.                 {
  2457.                         /* If it's a string object, activate it. */
  2458.  
  2459.                     if(GadgetList[i])
  2460.                     {
  2461.                         if(!(GadgetList[i] -> Flags & GFLG_DISABLED) && (GadgetList[i] -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2462.                         {
  2463.                             ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  2464.  
  2465.                             *IClass    = IDCMP_GADGETDOWN;
  2466.                             *Code    = 0;
  2467.                             *Gadget    = GadgetList[i];
  2468.  
  2469.                             break;
  2470.                         }
  2471.                     }
  2472.                 }
  2473.             }
  2474.         }
  2475.     }
  2476.  
  2477.         /* Conjure up the AmigaGuide help window. */
  2478.  
  2479.     if(*IClass == IDCMP_RAWKEY && *Code == 95)
  2480.         GuideSetup();
  2481. }
  2482.  
  2483.     /* SZ_ResetMaxWidth():
  2484.      *
  2485.      *    Reset maximum object width and return current maximum width.
  2486.      */
  2487.  
  2488. LONG
  2489. SZ_ResetMaxWidth()
  2490. {
  2491.     LONG Width = SZ_WidthMax;
  2492.  
  2493.     SZ_WidthMax = 0;
  2494.  
  2495.     return(Width);
  2496. }
  2497.  
  2498.     /* SZ_UpdateMaxWidth():
  2499.      *
  2500.      *    Update current maximum object width.
  2501.      */
  2502.  
  2503. VOID __regargs
  2504. SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  2505. {
  2506.     LONG Width = SZ_Width(Type,Title,Chars,Choices);
  2507.  
  2508.     if(Width > SZ_WidthMax)
  2509.         SZ_WidthMax = Width;
  2510. }
  2511.  
  2512.     /* SZ_GetWindowWidth():
  2513.      *
  2514.      *    Get the current window width.
  2515.      */
  2516.  
  2517. LONG
  2518. SZ_GetWindowWidth()
  2519. {
  2520.     return(SZ_WindowWidth);
  2521. }
  2522.  
  2523.     /* SZ_GetWindowHeight():
  2524.      *
  2525.      *    Get the current window height.
  2526.      */
  2527.  
  2528. LONG
  2529. SZ_GetWindowHeight()
  2530. {
  2531.     return(SZ_WindowHeight + SZ_Screen -> WBorBottom);
  2532. }
  2533.  
  2534.     /* SZ_GetLeftEdge():
  2535.      *
  2536.      *    Get the current object left edge.
  2537.      */
  2538.  
  2539. LONG
  2540. SZ_GetLeftEdge()
  2541. {
  2542.     return(SZ_CurrentLeft);
  2543. }
  2544.  
  2545.     /* SZ_GetTopEdge():
  2546.      *
  2547.      *    Get the current object top edge.
  2548.      */
  2549.  
  2550. LONG
  2551. SZ_GetTopEdge()
  2552. {
  2553.     return(SZ_CurrentTop);
  2554. }
  2555.  
  2556.     /* SZ_SetTopEdge(LONG Top):
  2557.      *
  2558.      *    Set the current object top edge.
  2559.      */
  2560.  
  2561. VOID __regargs
  2562. SZ_SetTopEdge(LONG Top)
  2563. {
  2564.     SZ_CurrentTop = Top;
  2565. }
  2566.  
  2567.     /* SZ_SetLeftEdge(LONG Left):
  2568.      *
  2569.      *    Set the current object left edge.
  2570.      */
  2571.  
  2572. VOID __regargs
  2573. SZ_SetLeftEdge(LONG Left)
  2574. {
  2575.     SZ_CurrentLeft = Left;
  2576. }
  2577.  
  2578.     /* SZ_SetAbsoluteTop(LONG Top):
  2579.      *
  2580.      *    Set new inner window top edge.
  2581.      */
  2582.  
  2583. VOID __regargs
  2584. SZ_SetAbsoluteTop(LONG Top)
  2585. {
  2586.     SZ_Top = Top;
  2587. }
  2588.  
  2589.     /* SZ_SetAbsoluteLeft(LONG Left):
  2590.      *
  2591.      *    Set new inner window left edge.
  2592.      */
  2593.  
  2594. VOID __regargs
  2595. SZ_SetAbsoluteLeft(LONG Left)
  2596. {
  2597.     SZ_Left = Left;
  2598. }
  2599.  
  2600.     /* SZ_SetWidth(LONG Width):
  2601.      *
  2602.      *    Set current object width.
  2603.      */
  2604.  
  2605. VOID __regargs
  2606. SZ_SetWidth(LONG Width)
  2607. {
  2608.     SZ_CurrentWidth = Width;
  2609. }
  2610.  
  2611. VOID
  2612. SZ_InitWidth()
  2613. {
  2614.     SZ_WindowWidth = SZ_Left + SZ_CurrentWidth + InterWidth;
  2615. }
  2616.  
  2617.     /* SZ_GetDimension(LONG *Width,LONG *Height):
  2618.      *
  2619.      *    Get current window dimensions.
  2620.      */
  2621.  
  2622. VOID __regargs
  2623. SZ_GetDimension(LONG *Width,LONG *Height)
  2624. {
  2625.     *Width    = SZ_WindowWidth;
  2626.     *Height    = SZ_WindowHeight + SZ_Screen -> WBorBottom;
  2627. }
  2628.  
  2629.     /* SZ_GetChecked(struct Gadget *Gadget):
  2630.      *
  2631.      *    Return whether a checkbox gadget is checked or not.
  2632.      */
  2633.  
  2634. BYTE __regargs
  2635. SZ_GetChecked(struct Gadget *Gadget)
  2636. {
  2637.     if(Gadget -> Flags & GFLG_SELECTED)
  2638.         return((BYTE)TRUE);
  2639.     else
  2640.         return((BYTE)FALSE);
  2641. }
  2642.  
  2643.     /* SZ_GetInteger(struct Gadget *Gadget):
  2644.      *
  2645.      *    Return the current settings of an integer gadget.
  2646.      */
  2647.  
  2648. LONG __regargs
  2649. SZ_GetInteger(struct Gadget *Gadget)
  2650. {
  2651.     if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2652.         return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> LongInt);
  2653.     else
  2654.         return(0);
  2655. }
  2656.  
  2657.     /* SZ_GetString(struct Gadget *Gadget):
  2658.      *
  2659.      *    Returns the contents of a string gadet.
  2660.      */
  2661.  
  2662. STRPTR __regargs
  2663. SZ_GetString(struct Gadget *Gadget)
  2664. {
  2665.     struct GadgetSupportInfo *Info;
  2666.  
  2667.         /* Does the object in question have an info structure attached? */
  2668.  
  2669.     if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  2670.     {
  2671.             /* Does the data look sensible? */
  2672.  
  2673.         if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  2674.         {
  2675.             if(Info -> Kind == PASSWORD_KIND)
  2676.                 return(Info -> Buffer);
  2677.         }
  2678.     }
  2679.  
  2680.     if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2681.         return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> Buffer);
  2682.     else
  2683.         return("");
  2684. }
  2685.  
  2686.     /* SZ_TextWidth(STRPTR String):
  2687.      *
  2688.      *    Determine string width in pixels.
  2689.      */
  2690.  
  2691. LONG __regargs
  2692. SZ_TextWidth(STRPTR String)
  2693. {
  2694.     UBYTE    TempString[256];
  2695.     WORD    i,j;
  2696.     BYTE    LastSpace = FALSE;
  2697.  
  2698.     for(i = j = 0 ; String[i] ; i++)
  2699.     {
  2700.         if(String[i] == ' ')
  2701.             LastSpace = TRUE;
  2702.         else
  2703.             LastSpace = FALSE;
  2704.  
  2705.         if(String[i] != '_')
  2706.             TempString[j++] = String[i];
  2707.     }
  2708.  
  2709.     if(LastSpace)
  2710.     {
  2711.         TempString[j] = 0;
  2712.  
  2713.         String = NewTitle(TempString,0,NULL,FALSE);
  2714.  
  2715.         j = strlen(String);
  2716.  
  2717.         return(TextLength(SZ_RPort,String,j));
  2718.     }
  2719.     else
  2720.         return(TextLength(SZ_RPort,TempString,j));
  2721. }
  2722.  
  2723.     /* SZ_AddLeftOffset(LONG Offset):
  2724.      *
  2725.      *    Update current object left offset.
  2726.      */
  2727.  
  2728. VOID __regargs
  2729. SZ_AddLeftOffset(LONG Offset)
  2730. {
  2731.     SZ_CurrentLeft += Offset;
  2732. }
  2733.  
  2734.     /* SZ_LeftOffsetN(LONG DataArray,...):
  2735.      *
  2736.      *    Determine the maximum length of a number of
  2737.      *    gadget labels (first, second, third item, -1 terminates
  2738.      *    the array).
  2739.      */
  2740.  
  2741. LONG __stdargs
  2742. SZ_LeftOffsetN(LONG DataArray,...)
  2743. {
  2744.     extern STRPTR __regargs    LocaleString(LONG ID);
  2745.  
  2746.     LONG    *Data = &DataArray,
  2747.          Len,
  2748.          Max = 0;
  2749.  
  2750.     while(*Data != -1)
  2751.     {
  2752.         if((Len = SZ_TextWidth(LocaleString(*Data++))) > Max)
  2753.             Max = Len;
  2754.     }
  2755.  
  2756.     return(Max + INTERWIDTH);
  2757. }
  2758.  
  2759.     /* SZ_LeftOffsetDelta(LONG From,LONG To):
  2760.      *
  2761.      *    Determine the maximum length of a number of
  2762.      *    gadget labels (given as first and last gadget).
  2763.      */
  2764.  
  2765. LONG __regargs
  2766. SZ_LeftOffsetDelta(LONG From,LONG To)
  2767. {
  2768.     extern STRPTR __regargs    LocaleString(LONG ID);
  2769.  
  2770.     LONG    i,
  2771.         Len,
  2772.         Max = 0;
  2773.  
  2774.     for(i = From ; i <= To ; i++)
  2775.     {
  2776.         if((Len = SZ_TextWidth(LocaleString(i))) > Max)
  2777.             Max = Len;
  2778.     }
  2779.  
  2780.     return(Max + INTERWIDTH);
  2781. }
  2782.  
  2783.     /* SZ_SizeCleanup():
  2784.      *
  2785.      *    Free data allocated by SZ_SizeSetup().
  2786.      */
  2787.  
  2788. VOID
  2789. SZ_SizeCleanup()
  2790. {
  2791.     if(SZ_TextFont)
  2792.     {
  2793.         CloseFont(SZ_TextFont);
  2794.  
  2795.         SZ_TextFont = NULL;
  2796.     }
  2797.  
  2798.     if(SZ_RPort)
  2799.     {
  2800.         FreeVec(SZ_RPort);
  2801.  
  2802.         SZ_RPort = NULL;
  2803.     }
  2804. }
  2805.  
  2806.     /* SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title):
  2807.      *
  2808.      *    Perform setups for gadget creation.
  2809.      */
  2810.  
  2811. BYTE __regargs
  2812. SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title)
  2813. {
  2814.     struct DrawInfo *DrawInfo;
  2815.  
  2816.     SZ_SizeCleanup();
  2817.  
  2818.     if(DrawInfo = GetScreenDrawInfo(Screen))
  2819.     {
  2820.         SZ_TextPen = DrawInfo -> dri_Pens[TEXTPEN];
  2821.  
  2822.         FreeScreenDrawInfo(Screen,DrawInfo);
  2823.     }
  2824.  
  2825.     SZ_Screen = Screen;
  2826.  
  2827.     if(SZ_RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY | MEMF_CLEAR))
  2828.     {
  2829.         InitRastPort(SZ_RPort);
  2830.  
  2831.         if(!TextAttr)
  2832.             TextAttr = Screen -> Font;
  2833.  
  2834.         if(SZ_TextFont = (struct TextFont *)OpenDiskFont(TextAttr))
  2835.         {
  2836.             UWORD    i,Width;
  2837.             UBYTE    Char;
  2838.  
  2839.             InterWidth = INTERWIDTH;
  2840.  
  2841.             if(SZ_TextFont -> tf_YSize <= 8)
  2842.                 InterHeight = 1;
  2843.             else
  2844.                 InterHeight = SZ_TextFont -> tf_YSize / 4;
  2845.  
  2846.             SetFont(SZ_RPort,SZ_TextFont);
  2847.  
  2848.             SZ_AverageGlyphWidth    = 0;
  2849.             SZ_MaxGlyphWidth    = 0;
  2850.             SZ_MaxNumericWidth    = 0;
  2851.  
  2852.             for(i = 0 ; i < 256 ; i++)
  2853.             {
  2854.                 Char = i;
  2855.  
  2856.                 Width = TextLength(SZ_RPort,&Char,1);
  2857.  
  2858.                 if(Width > SZ_MaxGlyphWidth)
  2859.                     SZ_MaxGlyphWidth = Width;
  2860.  
  2861.                 SZ_AverageGlyphWidth += Width;
  2862.             }
  2863.  
  2864.             SZ_AverageGlyphWidth /= 256;
  2865.  
  2866.             for(i = '0' ; i <= '0' ; i++)
  2867.             {
  2868.                 Char = i;
  2869.  
  2870.                 if((Width = TextLength(SZ_RPort,&Char,1)) > SZ_MaxNumericWidth)
  2871.                     SZ_MaxNumericWidth = Width;
  2872.             }
  2873.  
  2874.             if((Width = TextLength(SZ_RPort," ",1)) > SZ_MaxNumericWidth)
  2875.                 SZ_MaxNumericWidth = Width;
  2876.  
  2877.             if((Width = TextLength(SZ_RPort,",",1)) > SZ_MaxNumericWidth)
  2878.                 SZ_MaxNumericWidth = Width;
  2879.  
  2880.             if((Width = TextLength(SZ_RPort,".",1)) > SZ_MaxNumericWidth)
  2881.                 SZ_MaxNumericWidth = Width;
  2882.  
  2883.             if(SZ_AverageGlyphWidth > SZ_MaxNumericWidth)
  2884.                 SZ_MaxNumericWidth = SZ_AverageGlyphWidth;
  2885.  
  2886.             if(Title)
  2887.                 SZ_Top    = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + InterHeight;
  2888.             else
  2889.                 SZ_Top    = Screen -> WBorTop + InterHeight;
  2890.  
  2891.             SZ_Left        = InterWidth;
  2892.  
  2893.             SZ_CurrentLeft    = InterWidth;
  2894.             SZ_CurrentTop    = SZ_Top;
  2895.  
  2896.             SZ_WindowWidth    = 0;
  2897.             SZ_WindowHeight    = 0;
  2898.  
  2899.             SZ_CurrentWidth    = 0;
  2900.             SZ_MaxWidth    = 0;
  2901.  
  2902.             return(TRUE);
  2903.         }
  2904.     }
  2905.  
  2906.     SZ_SizeCleanup();
  2907.  
  2908.     return(FALSE);
  2909. }
  2910.  
  2911.     /* SZ_GetNumericLen(STRPTR String):
  2912.      *
  2913.      *    Get the string pixel width, measured using the maximum
  2914.      *    numeric glyph width.
  2915.      */
  2916.  
  2917. ULONG __regargs
  2918. SZ_GetNumericLen(STRPTR String)
  2919. {
  2920.     return(strlen(String) * SZ_MaxNumericWidth);
  2921. }
  2922.  
  2923.     /* SZ_GetGlyphLen(STRPTR String):
  2924.      *
  2925.      *    Get the string pixel width, measured using the maximum
  2926.      *    glyph width.
  2927.      */
  2928.  
  2929. ULONG __regargs
  2930. SZ_GetGlyphLen(STRPTR String)
  2931. {
  2932.     return(strlen(String) * SZ_MaxGlyphWidth);
  2933. }
  2934.  
  2935.     /* SZ_GetLen(STRPTR String):
  2936.      *
  2937.      *    Get the string pixel width, measured using the average
  2938.      *    glyph width.
  2939.      */
  2940.  
  2941. ULONG __regargs
  2942. SZ_GetLen(STRPTR String)
  2943. {
  2944.     return(strlen(String) * SZ_AverageGlyphWidth);
  2945. }
  2946.  
  2947.     /* SZ_Height(UBYTE Type,LONG Lines,BYTE Display):
  2948.      *
  2949.      *    Determine the height of an object.
  2950.      */
  2951.  
  2952. LONG __regargs
  2953. SZ_Height(UBYTE Type,LONG Lines,BYTE Display)
  2954. {
  2955.     LONG Height = 0;
  2956.  
  2957.     switch(Type)
  2958.     {
  2959.         case LISTVIEW_KIND:
  2960.  
  2961.             Height = 4 + Lines * SZ_TextFont -> tf_YSize + 4;
  2962.  
  2963.             if(Display == SZLV_Display)
  2964.                 Height += 2 + SZ_TextFont -> tf_YSize + 2;
  2965.  
  2966.             if(Display == SZLV_String)
  2967.                 Height += 3 + SZ_TextFont -> tf_YSize + 3;
  2968.  
  2969.             break;
  2970.  
  2971.         case FILE_KIND:
  2972.         case FOLDER_KIND:
  2973.         case SCREEN_KIND:
  2974.  
  2975.             if(SZ_TextFont -> tf_YSize < 6)
  2976.                 Height = 12;
  2977.             else
  2978.                 Height = 3 + SZ_TextFont -> tf_YSize + 3;
  2979.  
  2980.             break;
  2981.  
  2982.         case PASSWORD_KIND:
  2983.         case INTEGER_KIND:
  2984.         case STRING_KIND:
  2985.  
  2986.             Height = 3 + SZ_TextFont -> tf_YSize + 3;
  2987.             break;
  2988.  
  2989.         case CYCLE_KIND:
  2990.         case TEXT_KIND:
  2991.         case BUTTON_KIND:
  2992.  
  2993.             Height = 2 + SZ_TextFont -> tf_YSize + 2;
  2994.             break;
  2995.  
  2996.         case CHECKBOX_KIND:
  2997.  
  2998.             if(SZ_TextFont -> tf_YSize < 11)
  2999.                 Height = 11;
  3000.             else
  3001.                 Height = SZ_TextFont -> tf_YSize;
  3002.  
  3003.             break;
  3004.  
  3005.         case SLIDER_KIND:
  3006.  
  3007.             Height = 1 + SZ_TextFont -> tf_YSize + 1;
  3008.             break;
  3009.  
  3010.         case MX_KIND:
  3011.  
  3012.             Height = Lines * (SZ_TextFont -> tf_YSize + 1) - 1;
  3013.             break;
  3014.  
  3015.         case PALETTE_KIND:
  3016.  
  3017.             Height = 2 * SZ_TextFont -> tf_YSize;
  3018.             break;
  3019.     }
  3020.  
  3021.     return(Height);
  3022. }
  3023.  
  3024.     /* SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices):
  3025.      *
  3026.      *    Determine the width of an object.
  3027.      */
  3028.  
  3029. LONG __regargs
  3030. SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  3031. {
  3032.     LONG    Width = 0,
  3033.         Len,Max = 0,i;
  3034.  
  3035.     switch(Type)
  3036.     {
  3037.         case LISTVIEW_KIND:
  3038.  
  3039.             Width = (4 + Chars * SZ_AverageGlyphWidth + 4) + (2 + 2 * SZ_AverageGlyphWidth + 2) + 4;    /* KLUDGE + 4 */
  3040.             break;
  3041.  
  3042.         case TEXT_KIND:
  3043.         case BUTTON_KIND:
  3044.  
  3045.             if(Title)
  3046.                 Width = 6 + SZ_TextWidth(Title) + 6;
  3047.             else
  3048.                 Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
  3049.  
  3050.             break;
  3051.  
  3052.         case FILE_KIND:
  3053.         case FOLDER_KIND:
  3054.         case SCREEN_KIND:
  3055.  
  3056.             if(SZ_AverageGlyphWidth <= 10)
  3057.                 Width = 20;
  3058.             else
  3059.                 Width = 2 * SZ_AverageGlyphWidth;
  3060.  
  3061.             if(Chars)
  3062.                 Width = 6 + Chars * SZ_AverageGlyphWidth + 6 - (2 + Width);
  3063.  
  3064.             break;
  3065.  
  3066.         case PASSWORD_KIND:
  3067.         case SLIDER_KIND:
  3068.         case STRING_KIND:
  3069.         case INTEGER_KIND:
  3070.  
  3071.             Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
  3072.             break;
  3073.  
  3074.         case CHECKBOX_KIND:
  3075.  
  3076.             if(SZ_AverageGlyphWidth < 13)
  3077.                 Width = 26;
  3078.             else
  3079.                 Width = 2 * SZ_AverageGlyphWidth;
  3080.  
  3081.             break;
  3082.  
  3083.         case CYCLE_KIND:
  3084.  
  3085.             if(Choices)
  3086.             {
  3087.                 for(i = 0 ; Choices[i] ; i++)
  3088.                 {
  3089.                     if((Len = TextLength(SZ_RPort,Choices[i],strlen(Choices[i]))) > Max)
  3090.                         Max = Len;
  3091.                 }
  3092.  
  3093.                 Width = 24 + Max + 4;
  3094.             }
  3095.             else
  3096.                 Width = 24 + Chars * SZ_AverageGlyphWidth + 4;
  3097.  
  3098.             break;
  3099.  
  3100.         case MX_KIND:
  3101.  
  3102.             if(SZ_AverageGlyphWidth < 8)
  3103.                 Width = 17;
  3104.             else
  3105.                 Width = 2 * SZ_AverageGlyphWidth;
  3106.  
  3107.             break;
  3108.     }
  3109.  
  3110.     return(Width);
  3111. }
  3112.  
  3113.     /* SZ_FreeBox(struct TextBox *Box):
  3114.      *
  3115.      *    Free a text box.
  3116.      */
  3117.  
  3118. VOID __regargs
  3119. SZ_FreeBox(struct TextBox *Box)
  3120. {
  3121.     if(Box)
  3122.     {
  3123.         if(Box -> Text)
  3124.         {
  3125.             LONG i;
  3126.  
  3127.             for(i = 0 ; i < Box -> NumLines ; i++)
  3128.             {
  3129.                 if(Box -> Text[i])
  3130.                     FreeVec(Box -> Text[i]);
  3131.             }
  3132.  
  3133.             FreeVec(Box -> Text);
  3134.         }
  3135.  
  3136.         if(Box -> Title)
  3137.             FreeVec(Box -> Title);
  3138.  
  3139.         FreeVec(Box);
  3140.     }
  3141. }
  3142.  
  3143.     /* SZ_FreeBoxes(struct TextBox *FirstBox):
  3144.      *
  3145.      *    Free a number of text boxes.
  3146.      */
  3147.  
  3148. VOID __regargs
  3149. SZ_FreeBoxes(struct TextBox *FirstBox)
  3150. {
  3151.     if(FirstBox)
  3152.     {
  3153.         struct TextBox *NextBox;
  3154.  
  3155.         do
  3156.         {
  3157.             NextBox = FirstBox -> NextBox;
  3158.  
  3159.             SZ_FreeBox(FirstBox);
  3160.  
  3161.             FirstBox = NextBox;
  3162.         }
  3163.         while(FirstBox);
  3164.     }
  3165. }
  3166.  
  3167.     /* SZ_BoxWidth(LONG Chars):
  3168.      *
  3169.      *    Determine the width of a text box.
  3170.      */
  3171.  
  3172. LONG __regargs
  3173. SZ_BoxWidth(LONG Chars)
  3174. {
  3175.     return((LONG)(4 + SZ_AverageGlyphWidth * Chars + 4));
  3176. }
  3177.  
  3178.     /* SZ_BoxHeight(LONG Lines):
  3179.      *
  3180.      *    Determine the height of a text box.
  3181.      */
  3182.  
  3183. LONG __regargs
  3184. SZ_BoxHeight(LONG Lines)
  3185. {
  3186.     return(2 + SZ_TextFont -> tf_YSize * Lines + 2);
  3187. }
  3188.  
  3189.     /* SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen):
  3190.      *
  3191.      *    Set the text box list title text rendering pens.
  3192.      */
  3193.  
  3194. VOID __regargs
  3195. SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen)
  3196. {
  3197.     while(Box)
  3198.     {
  3199.         Box -> TitleFgPen = FgPen;
  3200.         Box -> TitleBgPen = BgPen;
  3201.  
  3202.         Box = Box -> NextBox;
  3203.     }
  3204. }
  3205.  
  3206.     /* SZ_CreateTextBox(struct TextBox **FirstBox,...):
  3207.      *
  3208.      *    Create a text box, this routine works similar
  3209.      *    to the CreateGadget() frontend.
  3210.      */
  3211.  
  3212. struct TextBox * __stdargs
  3213. SZ_CreateTextBox(struct TextBox **FirstBox,...)
  3214. {
  3215.     va_list                 VarArgs;
  3216.     struct TagItem            *TagList,
  3217.                     *ThisTag;
  3218.     LONG                 Chars,Lines,
  3219.                      Width,
  3220.                      Height,
  3221.                      Left = SZ_CurrentLeft;
  3222.     BYTE                 AutoWidth    = FALSE,
  3223.                      MoveDown    = TRUE,
  3224.                      SetLeft    = FALSE,
  3225.                      SetBelow    = FALSE;
  3226.  
  3227.     struct TextBox            *Box;
  3228.     LONG                 i;
  3229.  
  3230.     va_start(VarArgs,FirstBox);
  3231.  
  3232.     TagList = (struct TagItem *)VarArgs;
  3233.  
  3234.     if(ThisTag = FindTagItem(SZ_Lines,TagList))
  3235.         Lines = (LONG)ThisTag -> ti_Data;
  3236.     else
  3237.         return(NULL);
  3238.  
  3239.     Height = 2 + SZ_TextFont -> tf_YSize * Lines + 2;
  3240.  
  3241.     if(ThisTag = FindTagItem(SZ_Chars,TagList))
  3242.         Chars = (LONG)ThisTag -> ti_Data;
  3243.     else
  3244.     {
  3245.         if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  3246.             AutoWidth = ThisTag -> ti_Data;
  3247.  
  3248.         if(!AutoWidth)
  3249.             return(NULL);
  3250.         else
  3251.             Chars = (SZ_CurrentWidth - 8) / SZ_AverageGlyphWidth;
  3252.     }
  3253.  
  3254.     if(!(Box = (struct TextBox *)AllocVec(sizeof(struct TextBox),MEMF_ANY | MEMF_CLEAR)))
  3255.         return(NULL);
  3256.  
  3257.     if(ThisTag = FindTagItem(SZ_SaveX,TagList))
  3258.         SetLeft = ThisTag -> ti_Data;
  3259.  
  3260.     if(ThisTag = FindTagItem(SZ_SaveY,TagList))
  3261.         SetBelow = ThisTag -> ti_Data;
  3262.  
  3263.     if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  3264.     {
  3265.         if(ThisTag -> ti_Data)
  3266.             SZ_CurrentTop = SZ_WindowHeight;
  3267.     }
  3268.  
  3269.     if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  3270.     {
  3271.         if(ThisTag -> ti_Data)
  3272.             SZ_CurrentTop += InterHeight;
  3273.     }
  3274.  
  3275.     if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  3276.     {
  3277.         if(ThisTag -> ti_Data)
  3278.         {
  3279.             SZ_CurrentTop    = SZ_Top;
  3280.             Left        = Left + SZ_MaxWidth + InterWidth;
  3281.  
  3282.             SZ_MaxWidth    = 0;
  3283.         }
  3284.     }
  3285.  
  3286.     if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  3287.         AutoWidth = ThisTag -> ti_Data;
  3288.  
  3289.     if(!AutoWidth)
  3290.         Width = SZ_BoxWidth(Chars);
  3291.     else
  3292.         Width = SZ_CurrentWidth;
  3293.  
  3294.     if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  3295.     {
  3296.         if(ThisTag -> ti_Data)
  3297.         {
  3298.             Left = SZ_Left;
  3299.  
  3300.             MoveDown = FALSE;
  3301.         }
  3302.     }
  3303.  
  3304.     if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  3305.     {
  3306.         if(ThisTag -> ti_Data)
  3307.         {
  3308.             Left = SZ_WindowWidth - INTERWIDTH - Width;
  3309.  
  3310.             MoveDown = FALSE;
  3311.         }
  3312.     }
  3313.  
  3314.     if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  3315.     {
  3316.         if(ThisTag -> ti_Data)
  3317.         {
  3318.             Left = (SZ_WindowWidth - Width) / 2;
  3319.  
  3320.             MoveDown = FALSE;
  3321.         }
  3322.     }
  3323.  
  3324.     if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  3325.     {
  3326.         LONG Count = ThisTag -> ti_Data,Width = SZ_WindowWidth;
  3327.  
  3328.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  3329.         {
  3330.             Width -= ThisTag -> ti_Data - InterWidth;
  3331.  
  3332.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  3333.             SZ_GroupX    = Left = ThisTag -> ti_Data;
  3334.         }
  3335.         else
  3336.         {
  3337.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  3338.             SZ_GroupX    = Left = SZ_Left;
  3339.         }
  3340.  
  3341.         MoveDown = FALSE;
  3342.     }
  3343.     else
  3344.     {
  3345.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  3346.             Left = ThisTag -> ti_Data;
  3347.     }
  3348.  
  3349.     if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  3350.     {
  3351.         if(ThisTag -> ti_Data)
  3352.         {
  3353.             SZ_GroupX += SZ_GroupDelta;
  3354.  
  3355.             Left = SZ_GroupX;
  3356.  
  3357.             MoveDown = FALSE;
  3358.         }
  3359.     }
  3360.  
  3361.     if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  3362.         SZ_CurrentTop = ThisTag -> ti_Data;
  3363.  
  3364.     Box -> Left        = Left;
  3365.     Box -> Top        = SZ_CurrentTop;
  3366.     Box -> Width        = Width;
  3367.     Box -> Height        = Height;
  3368.  
  3369.     Box -> LineWidth    = Chars * SZ_AverageGlyphWidth;
  3370.     Box -> LineHeight    = SZ_TextFont -> tf_YSize;
  3371.  
  3372.     Box -> NumChars        = Chars;
  3373.     Box -> NumLines        = Lines;
  3374.  
  3375.     Box -> TitleFgPen    = SZ_TextPen;
  3376.     Box -> TitleBgPen    = 0;
  3377.     Box -> TextPen        = SZ_TextPen;
  3378.  
  3379.     if(!(Box -> Title = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  3380.     {
  3381.         SZ_FreeBox(Box);
  3382.  
  3383.         return(NULL);
  3384.     }
  3385.  
  3386.     if(!(Box -> Text = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  3387.     {
  3388.         SZ_FreeBox(Box);
  3389.  
  3390.         return(NULL);
  3391.     }
  3392.  
  3393.     for(i = 0 ; i < Lines ; i++)
  3394.     {
  3395.         if(!(Box -> Text[i] = (STRPTR)AllocVec(Chars + 1,MEMF_ANY | MEMF_CLEAR)))
  3396.         {
  3397.             SZ_FreeBox(Box);
  3398.  
  3399.             return(NULL);
  3400.         }
  3401.     }
  3402.  
  3403.     if(SetBelow)
  3404.         MoveDown = FALSE;
  3405.  
  3406.     if(MoveDown)
  3407.     {
  3408.         SZ_CurrentTop = SZ_CurrentTop + Height + InterHeight;
  3409.  
  3410.         if(SZ_CurrentTop > SZ_WindowHeight)
  3411.             SZ_WindowHeight = SZ_CurrentTop;
  3412.     }
  3413.     else
  3414.     {
  3415.         if(SZ_CurrentTop + Height + InterHeight > SZ_WindowHeight)
  3416.             SZ_WindowHeight = SZ_CurrentTop + Height + InterHeight;
  3417.  
  3418.         SZ_MaxWidth = 0;
  3419.     }
  3420.  
  3421.     if(Width > SZ_MaxWidth)
  3422.         SZ_MaxWidth = Width;
  3423.  
  3424.     if(Left + SZ_MaxWidth + INTERWIDTH > SZ_WindowWidth)
  3425.         SZ_WindowWidth = Left + SZ_MaxWidth + INTERWIDTH;
  3426.  
  3427.     if(!SetLeft)
  3428.         SZ_CurrentLeft = Left;
  3429.  
  3430.     if(!(*FirstBox))
  3431.         *FirstBox = Box;
  3432.     else
  3433.     {
  3434.         struct TextBox *CurrentBox = *FirstBox;
  3435.  
  3436.         while(CurrentBox -> NextBox)
  3437.             CurrentBox = CurrentBox -> NextBox;
  3438.  
  3439.         CurrentBox -> NextBox = Box;
  3440.     }
  3441.  
  3442.     return(Box);
  3443. }
  3444.  
  3445.     /* SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...):
  3446.      *
  3447.      *    Set the titles displayed in a text box.
  3448.      */
  3449.  
  3450. VOID __stdargs
  3451. SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...)
  3452. {
  3453.     if(Box)
  3454.     {
  3455.         STRPTR    *Data = &Array;
  3456.         LONG     i = 0;
  3457.  
  3458.         while(*Data != NULL)
  3459.         {
  3460.             if(i < Box -> NumLines)
  3461.                 Box -> Title[i++] = *Data;
  3462.  
  3463.             Data++;
  3464.         }
  3465.     }
  3466. }
  3467.  
  3468.     /* SZ_SetLine():
  3469.      *
  3470.      *    Print a string into a text box, plain version.
  3471.      */
  3472.  
  3473. VOID __regargs
  3474. SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String)
  3475. {
  3476.     BYTE         FgPen    = ReadAPen(RPort),
  3477.              BgPen    = ReadBPen(RPort),
  3478.              DrMd    = ReadDrMd(RPort);
  3479.     struct TextFont    *Font    = RPort -> Font;
  3480.  
  3481.     LONG         Width,Len,
  3482.              Left    = Box -> Left + 4,
  3483.              Top    = Box -> Top + 2 + Line * Box -> LineHeight;
  3484.  
  3485.     if(DrMd != JAM2)
  3486.         SetDrMd(RPort,JAM2);
  3487.  
  3488.     if(FgPen != Box -> TextPen)
  3489.         SetAPen(RPort,Box -> TextPen);
  3490.  
  3491.     if(BgPen != 0)
  3492.         SetBPen(RPort,0);
  3493.  
  3494.     if(Font != UserTextFont)
  3495.         SetFont(RPort,UserTextFont);
  3496.  
  3497.     if(Len = strlen(String))
  3498.     {
  3499.         if(Len > Box -> NumChars)
  3500.             Len = Box -> NumChars;
  3501.  
  3502.         while(Len > 0 && TextLength(RPort,String,Len) > Box -> LineWidth)
  3503.             Len--;
  3504.  
  3505.         if(Len)
  3506.         {
  3507.             Width = TextLength(RPort,String,Len);
  3508.  
  3509.             Move(RPort,Left,Top + RPort -> Font -> tf_Baseline);
  3510.             Text(RPort,String,Len);
  3511.         }
  3512.         else
  3513.             Width = 0;
  3514.     }
  3515.     else
  3516.         Width = 0;
  3517.  
  3518.     if(Width != Box -> LineWidth)
  3519.     {
  3520.         if(FgPen != 0)
  3521.         {
  3522.             SetAPen(RPort,0);
  3523.  
  3524.             RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
  3525.  
  3526.             SetAPen(RPort,FgPen);
  3527.         }
  3528.         else
  3529.             RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
  3530.     }
  3531.  
  3532.     if(DrMd != JAM2)
  3533.         SetDrMd(RPort,DrMd);
  3534.  
  3535.     if(String != Box -> Text[Line])
  3536.     {
  3537.         if(Len > 0)
  3538.             memcpy(Box -> Text[Line],String,Len);
  3539.  
  3540.         Box -> Text[Line][Len] = 0;
  3541.     }
  3542.  
  3543.     if(Font != UserTextFont)
  3544.         SetFont(RPort,Font);
  3545.  
  3546.     if(BgPen != 0)
  3547.         SetBPen(RPort,BgPen);
  3548.  
  3549.     SetAPen(RPort,FgPen);
  3550. }
  3551.  
  3552.     /* SZ_PrintLine():
  3553.      *
  3554.      *    Print a string into a text box, varargs version.
  3555.      */
  3556.  
  3557. VOID __stdargs
  3558. SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...)
  3559. {
  3560.     extern VOID __stdargs VSPrintf(APTR,STRPTR,va_list);
  3561.  
  3562.     va_list    VarArgs;
  3563.     UBYTE    Buffer[256];
  3564.  
  3565.     va_start(VarArgs,String);
  3566.     VSPrintf(Buffer,String,VarArgs);
  3567.     va_end(VarArgs);
  3568.  
  3569.     SZ_SetLine(RPort,Box,Line,Buffer);
  3570. }
  3571.  
  3572.     /* SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box):
  3573.      *
  3574.      *    (Re-)Draw a text box.
  3575.      */
  3576.  
  3577. VOID __regargs
  3578. SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box)
  3579. {
  3580.     if(Box)
  3581.     {
  3582.         LONG         LineY,i,Len,FgPen = ReadAPen(RPort),BgPen = ReadBPen(RPort),DrMd = ReadDrMd(RPort);
  3583.         struct TextFont    *Font = RPort -> Font;
  3584.  
  3585.         if(Font != UserTextFont)
  3586.             SetFont(RPort,UserTextFont);
  3587.  
  3588.         if(FgPen != 0)
  3589.         {
  3590.             SetAPen(RPort,0);
  3591.  
  3592.             RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
  3593.  
  3594.             SetAPen(RPort,FgPen);
  3595.         }
  3596.         else
  3597.             RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
  3598.  
  3599.         DrawBevelBox(RPort,Box -> Left,Box -> Top,Box -> Width,Box -> Height,
  3600.             GT_VisualInfo,    VisualInfo,
  3601.             GTBB_Recessed,    TRUE,
  3602.         TAG_DONE);
  3603.  
  3604.         LineY = Box -> Top + 2 + RPort -> Font -> tf_Baseline;
  3605.  
  3606.         SetAPen(RPort,Box -> TitleFgPen);
  3607.         SetBPen(RPort,Box -> TitleBgPen);
  3608.         SetDrMd(RPort,JAM2);
  3609.  
  3610.         for(i = 0 ; i < Box -> NumLines ; i++)
  3611.         {
  3612.             if(Len = strlen(Box -> Title[i]))
  3613.             {
  3614.                 Move(RPort,Box -> Left - INTERWIDTH - TextLength(RPort,Box -> Title[i],Len),LineY);
  3615.                 Text(RPort,Box -> Title[i],Len);
  3616.             }
  3617.  
  3618.             LineY += Box -> LineHeight;
  3619.         }
  3620.  
  3621.         for(i = 0 ; i < Box -> NumLines ; i++)
  3622.             SZ_PrintLine(RPort,Box,i,Box -> Text[i]);
  3623.  
  3624.         SetAPen(RPort,FgPen);
  3625.         SetBPen(RPort,BgPen);
  3626.  
  3627.         SetDrMd(RPort,DrMd);
  3628.  
  3629.         if(Font != UserTextFont)
  3630.             SetFont(RPort,Font);
  3631.     }
  3632. }
  3633.  
  3634.     /* SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox):
  3635.      *
  3636.      *    (Re-)Draw a number of text boxes.
  3637.      */
  3638.  
  3639. VOID __regargs
  3640. SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox)
  3641. {
  3642.     do
  3643.         SZ_DrawBox(RPort,FirstBox);
  3644.     while(FirstBox = FirstBox -> NextBox);
  3645. }
  3646.  
  3647.     /* SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top):
  3648.      *
  3649.      *    Change the location of a text box.
  3650.      */
  3651.  
  3652. VOID __regargs
  3653. SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top)
  3654. {
  3655.     Box -> Left    += Left;
  3656.     Box -> Top    += Top;
  3657. }
  3658.  
  3659.     /* SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
  3660.      *
  3661.      *    Change the locations of a number of text boxes.
  3662.      */
  3663.  
  3664. VOID __regargs
  3665. SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
  3666. {
  3667.     do
  3668.         SZ_MoveBox(FirstBox,Left,Top);
  3669.     while(FirstBox = FirstBox -> NextBox);
  3670. }
  3671.  
  3672.     /* SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top):
  3673.      *
  3674.      *    Set the location of a text box.
  3675.      */
  3676.  
  3677. VOID __regargs
  3678. SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top)
  3679. {
  3680.     if(Left >= 0)
  3681.         Box -> Left = Left;
  3682.  
  3683.     if(Top >= 0)
  3684.         Box -> Top = Top;
  3685. }
  3686.  
  3687.     /* SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
  3688.      *
  3689.      *    Set the locations of a number of text boxes.
  3690.      */
  3691.  
  3692. VOID __regargs
  3693. SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
  3694. {
  3695.     do
  3696.         SZ_SetBox(FirstBox,Left,Top);
  3697.     while(FirstBox = FirstBox -> NextBox);
  3698. }
  3699.  
  3700.     /* SZ_GetBoxInfo(struct TextBox *Box,LONG Type):
  3701.      *
  3702.      *    Query information on a certain text box.
  3703.      */
  3704.  
  3705. LONG __regargs
  3706. SZ_GetBoxInfo(struct TextBox *Box,LONG Type)
  3707. {
  3708.     switch(Type)
  3709.     {
  3710.         case BOX_LEFT:
  3711.  
  3712.             return(Box -> Left);
  3713.  
  3714.         case BOX_TOP:
  3715.  
  3716.             return(Box -> Top);
  3717.  
  3718.         case BOX_WIDTH:
  3719.  
  3720.             return(Box -> Width);
  3721.  
  3722.         case BOX_HEIGHT:
  3723.  
  3724.             return(Box -> Height);
  3725.  
  3726.         default:
  3727.  
  3728.             return(0);
  3729.     }
  3730. }
  3731.